Logo Search packages:      
Sourcecode: ibutils version File versions  Download package

client.cpp

/*
 * Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * $Id$
 */

#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */
#include <fstream>    /* for file streams */
#include "msgmgr.h"     /* message manager */
#include "helper.h"     /* mad dumps */
#include "simmsg.h"     /* IB mgt simulator messages */
#include "tcpcomm.h"    /* generic server and client */
#include "ibms_client_api.h" /* interface we provide to C clients */

class IBMSClient : GenClient {
public:
  IBMSClient(char *srvHostName, unsigned short portNum):
    GenClient(srvHostName, portNum, sizeof(ibms_response_t)) {};

  int
  sendSimMsg(ibms_client_msg_t &request, ibms_response_t &response)
  {
    MSGREG(err1, 'E', "Fail to obtain valid response size ($ != $)",
           "server");
    MSGREG(info1, 'V', "Obtained remote result:$", "server");
    int reqLen = sizeof(ibms_client_msg_t);
    int resLen;

    sendMsg(reqLen, (char*)&request, resLen, (char*)&response);

    if (resLen != sizeof(ibms_response_t))
    {
      MSGSND(err1, resLen,  sizeof(ibms_response_t));
      return 1;
    }
    MSGSND(info1, ibms_get_resp_str(&response));
    return 0;
  };
};

/* we subclass the generic server to receive our own messages */
class IBMSClientInMsgs : public GenServer {
  ibms_pfn_receive_cb_t pfnIncommingMadCallback;
  void *incommingMadContext;

public:
  IBMSClientInMsgs(unsigned short portNum,
                   ibms_pfn_receive_cb_t cb, void *ctx):
    GenServer(portNum, sizeof(ibms_client_msg_t)) {
    incommingMadContext = ctx;
    pfnIncommingMadCallback = cb;
  };

  /* handle incoming messages */
  int proccessClientMsg(int clientSock,
                        int reqLen, char request[],
                        int &resLen, char *(pResponse[]));
};

int
IBMSClientInMsgs::proccessClientMsg(
  int clientSock,
  int reqLen,
  char request[],
  int &resLen,
  char *(pResponse[]))
{
  MSGREG(err1, 'E', "Message is not of ibms_client_msg_t size ($ != $)",
         "client");
  MSGREG(inf1, 'V', "Received:\n$","client");

  if (reqLen != sizeof(ibms_client_msg_t))
  {
    MSGSND(err1, reqLen, sizeof(ibms_client_msg_t));
    return 1;
  }

  ibms_client_msg_t *pReq = (ibms_client_msg_t*)request;

  MSGSND(inf1, ibms_get_msg_str(pReq));

  if (pReq->msg_type == IBMS_CLI_MSG_MAD)
  {
    if (pfnIncommingMadCallback != NULL)
    {
      pfnIncommingMadCallback( incommingMadContext, &(pReq->msg.mad));
    }
  }

  /* NOTE: the allocated buffer for the response is deallocated by
     the call from the GenServer::clientThreadMain */
  resLen = sizeof(ibms_response_t);
  *pResponse = new char[sizeof(ibms_response_t)];
  ibms_response_t *pResp = (ibms_response_t *)*pResponse;

  /* we always succeed for now */
  pResp->status = 0;

  return 0;
}

/* struct holding all information about one connection */
typedef struct _ibms_client_conn_rec {
  IBMSClient *pClient;
  IBMSClientInMsgs *pServer;
} ibms_client_conn_rec_t ;

/* obtain the simulator host name and port number */
void
__ibms_get_sim_host_n_port(
  char *hostName,
  unsigned short int &simPortNum)
{
  MSGREG(err1, 'F', "Fail to open:$","client");
  MSGREG(inf1, 'I', "Sim server:$ port:$","client");
  std::ifstream serverFile;
  std::string serverHost;

  std::string simDir;
  if (getenv("IBMGTSIM_DIR"))
    simDir = getenv("IBMGTSIM_DIR");
  else
    simDir = "/tmp/ibmgtsim";

  std::string serverFileName = simDir + "/ibmgtsim.server";

  serverFile.open(serverFileName.c_str());
  if (serverFile.fail())
  {
    MSGSND(err1, serverFileName);
    exit(1);
  }
  serverFile >> serverHost >> simPortNum;
  MSGSND(inf1, serverHost, simPortNum);
  serverFile.close();
  strcpy(hostName, serverHost.c_str());
  // simPortNum = 42561;
}

/* connect to the server to the port guid.
   Registering incoming messages callbacks */
ibms_conn_handle_t
ibms_connect(uint64_t portGuid,
             ibms_pfn_receive_cb_t receiveCb,
             void* context)
{
  unsigned short int serverPortNum;
  ibms_client_conn_rec_t clientConn;
  char hostName[32];
  unsigned short int simPortNum;
  unsigned int seed = (int)time(NULL);

  /* get the simulator hostname and port */
  __ibms_get_sim_host_n_port(hostName, simPortNum);

  /* create a client object and store in the map */
  clientConn.pClient = new IBMSClient(hostName, simPortNum);

  /* create a server and register it in the servers map */
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;      /* the message we receive back */

  /* iterate several times to find an available socket */
  int trys = 0;
  do {
    serverPortNum =
      (unsigned short int)((1.0*rand_r(&seed)/RAND_MAX)*(65535-1024)+1024);
    clientConn.pServer =
      new IBMSClientInMsgs( serverPortNum ,receiveCb, context);

    if (clientConn.pServer->isAlive())
      break;
    else
    {
      delete clientConn.pServer;
      clientConn.pServer = NULL;
    }

  } while (trys++ < 50);

  if (!clientConn.pServer)
  {
        printf("-E- Failed to connect to simulator!\n");
    return 0;
  }
  printf("-I- Connected to simulator!\n");

  char thisHostName[32];
  gethostname(thisHostName, sizeof(thisHostName)-1);

  /* connect to the given guid */
  request.msg_type = IBMS_CLI_MSG_CONN;
  request.msg.conn.port_num = 1;
  request.msg.conn.port_guid = portGuid;
  strcpy(request.msg.conn.host, thisHostName);
  request.msg.conn.in_msg_port = serverPortNum;

  if (clientConn.pClient->sendSimMsg(request, response))
  {
    MSGREG(err1, 'F', "Fail to send connect message.","client");
    MSGSND(err1);
    return 0;
  }

  if (response.status)
  {
    MSGREG(err2, 'F', "Fail to connect to guid:$","client");
    MSGSND(err2, portGuid);
    return 0;
  }

  ibms_client_conn_rec_t *pCon =
    (ibms_client_conn_rec_t*)malloc( sizeof(ibms_client_conn_rec_t) );
  pCon->pServer = clientConn.pServer;
  pCon->pClient = clientConn.pClient;

  return pCon;
}

/* bind to a specific mad messages */
int
ibms_bind(
  ibms_conn_handle_t conHdl,
  ibms_bind_msg_t *pBindMsg)
{
  ibms_client_conn_rec_t *pCon = (ibms_client_conn_rec_t*)conHdl;
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;      /* the message we receive back */

  /* send second message - bind to  */
  request.msg_type = IBMS_CLI_MSG_BIND;
  request.msg.bind = *pBindMsg;

  if (pCon->pClient->sendSimMsg(request, response))
    return 1;

  return response.status;
}

/* set port capabilities */
int
ibms_set_cap(
  ibms_conn_handle_t conHdl,
  ibms_cap_msg_t *pCapMsg)
{
  ibms_client_conn_rec_t *pCon = (ibms_client_conn_rec_t*)conHdl;
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;      /* the message we receive back */

  /* send second message - bind to  */
  request.msg_type = IBMS_CLI_MSG_CAP;
  request.msg.cap = *pCapMsg;

  if (pCon->pClient->sendSimMsg(request, response))
    return 1;

  return response.status;
}

/* send a message to the simulator */
int
ibms_send(
  ibms_conn_handle_t conHdl,
  ibms_mad_msg_t *pMadMsg)
{
  ibms_client_conn_rec_t *pCon = (ibms_client_conn_rec_t*)conHdl;
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;      /* the message we receive back */

  memset(&request.msg.mad, 0, sizeof(request.msg.mad));
  request.msg_type = IBMS_CLI_MSG_MAD;
  request.msg.mad = *pMadMsg;

  if (pCon->pClient->sendSimMsg(request, response))
    return 1;

  return response.status;
}

/* disconnect from the simulator */
int
ibms_disconnect(
  ibms_conn_handle_t conHdl)
{
  ibms_client_conn_rec_t *pCon = (ibms_client_conn_rec_t*)conHdl;
  delete pCon;
  return(0);
}

#ifdef BUILD_QUIT_CLIENT
int main(int argc, char *argv[])
{
  unsigned short servPort;       /* server port */
  char *hostName;                /* Server Host Name */
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;    /* the message we receive back */

  if ((argc < 2) || (argc > 3))  /* Test for correct number of arguments */
  {
    fprintf(stderr, "Usage: %s <Server Host> [<Server Port>]\n",
            argv[0]);
    exit(1);
  }

  hostName = argv[1];

  if (argc == 3)
    servPort = atoi(argv[2]);     /* Use given port, if any */
  else
    servPort = 42561;

  msgMgr(0x1, &std::cout);
  msgMgr().setVerbLevel(0x1);

  /* we start the client */
  IBMSClient client(hostName, servPort);

  /* send first message - client connect */
  request.msg_type = IBMS_CLI_MSG_QUIT;

  printf("Sending Quit Message ...\n");
  client.sendSimMsg(request, response);

  sleep(2);

  exit(0);
}
#endif

#ifdef BUILD_TEST_CLIENT
int main(int argc, char *argv[])
{
  unsigned short servPort;       /* server port */
  char *hostName;               /* Server Host Name */
  int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv()
                                    and total bytes read */
  ibms_client_msg_t request;     /* the message we send */
  ibms_response_t response;    /* the message we receive back */
  int msgLen = sizeof(ibms_client_msg_t);

  if ((argc < 2) || (argc > 3))  /* Test for correct number of arguments */
  {
    fprintf(stderr, "Usage: %s <Server Host> [<Server Port>]\n",
            argv[0]);
    exit(1);
  }


  hostName = argv[1];

  if (argc == 3)
    servPort = atoi(argv[2]);     /* Use given port, if any */
  else
    servPort = 42561;

  msgMgr(MsgShowAll, &std::cout);

  /* need to have our own incoming messages port - so start our own server */
  IBMSClientInMsgs *pServer = new IBMSClientInMsgs( 46281, NULL, NULL );
  sleep(1);
  /* we start the client */
  IBMSClient client(hostName, servPort);

  /* send first message - client connect */
  request.msg_type = IBMS_CLI_MSG_CONN;
  request.msg.conn.port_num = 1;
  request.msg.conn.port_guid = 0x0002c90000000002ULL;
  gethostname(request.msg.conn.host, sizeof(request.msg.conn.host)-1);
  request.msg.conn.host[sizeof(request.msg.conn.host)] = '\0';
  request.msg.conn.in_msg_port = 46281;

  client.sendSimMsg(request, response);

  sleep(1);

  /* send second message - bind to  */
  request.msg_type = IBMS_CLI_MSG_BIND;
  request.msg.bind.port = 1;
  request.msg.bind.qpn = 1;
  request.msg.bind.mgt_class = 0x81;
  request.msg.bind.method = 0x1;
  request.msg.bind.mask = IBMS_BIND_MASK_PORT |
    IBMS_BIND_MASK_QP | IBMS_BIND_MASK_CLASS | IBMS_BIND_MASK_METH;

  client.sendSimMsg(request, response);

  sleep(1);


  for(int i = 1; i < 10; i++)
  {
    memset(&request.msg.mad, 0, sizeof(request.msg.mad));
    request.msg_type = IBMS_CLI_MSG_MAD;
    request.msg.mad.addr.dlid = 0x1;
    request.msg.mad.addr.slid = 0x2;
    request.msg.mad.addr.sqpn = 0;
    request.msg.mad.addr.dqpn = 0;

    request.msg.mad.header.mgmt_class = 0x81;
    request.msg.mad.header.method = 0x1;
    request.msg.mad.header.trans_id = i;

    /* we will hard-code some direct route path */
    ib_smp_t *p_mad = (ib_smp_t *)(&request.msg.mad.header);
    p_mad->hop_count = 3;
    p_mad->hop_ptr = 0;
    p_mad->initial_path[1] = 1;
    p_mad->initial_path[2] = i;
    p_mad->initial_path[3] = 2;
    p_mad->dr_dlid = IB_LID_PERMISSIVE;
    p_mad->dr_slid = IB_LID_PERMISSIVE;

    client.sendSimMsg(request, response);

  }

  /* let us make it return to us */
  memset(&request.msg.mad, 0, sizeof(request.msg.mad));
  request.msg_type = IBMS_CLI_MSG_MAD;
  request.msg.mad.addr.dlid = 0x1;
  request.msg.mad.addr.slid = 0x2;
  request.msg.mad.addr.sqpn = 0;
  request.msg.mad.addr.dqpn = 0;

  request.msg.mad.header.mgmt_class = 0x81;
  request.msg.mad.header.method = 0x1;
  request.msg.mad.header.trans_id = 123456;

  /* we will hard-code some direct route path */
  ib_smp_t *p_mad = (ib_smp_t *)(&request.msg.mad.header);
  p_mad->hop_count = 4;
  p_mad->hop_ptr = 0;
  p_mad->initial_path[1] = 1;
  p_mad->initial_path[2] = 3;
  p_mad->initial_path[3] = 1;
  p_mad->initial_path[4] = 1;

  p_mad->dr_dlid = IB_LID_PERMISSIVE;
  p_mad->dr_slid = IB_LID_PERMISSIVE;

    client.sendSimMsg(request, response);

  sleep(10);
  request.msg_type = IBMS_CLI_MSG_DISCONN;
  request.msg.disc.port_num = 1;
  request.msg.disc.port_guid = 0x0002c90000000002ULL;

  client.sendSimMsg(request, response);

  delete pServer;

  exit(0);
}
#endif

Generated by  Doxygen 1.6.0   Back to index