#include "headers.h"
#include "myUtil.cc"
#pragma comment(lib, "Ws2_32.lib")

static int winsockFlag = 0;

void initWinsock(){
  WORD wVersionRequested; 
  WSADATA wsaData; 
  int err; 
  wVersionRequested = MAKEWORD(1, 1); 
  wVersionRequested = MAKEWORD(2, 0); 
  
  err = WSAStartup(wVersionRequested, &wsaData); 
    
  if (err != 0) {
    mexErrMsgTxt("WSAStartup() failed.");
  }
}

void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
  
  if (nrhs != 1){ 
    mexErrMsgTxt("need 1 input args");
  } else if (nlhs != 1){
    mexErrMsgTxt("need 1 output args");
  }
  char* ipAddressArgument = input2string(prhs[0]);
  
  /***********************************************/
  /* init winsock (only once) */
  /***********************************************/
  if (winsockFlag == 0){
    initWinsock();
    winsockFlag = 1;
  }

  /***********************************************/
  /* create a socket */
  /***********************************************/
  SOCKET s;  
  s = socket(AF_INET, SOCK_STREAM, 0);
  if (s == INVALID_SOCKET){
    mexErrMsgTxt("socket(): INVALID_SOCKET");
  }
  
  /***********************************************
   * turn off Nagle's algorithm, set immediate writing
   * as commands have side effects in realtime
   ***********************************************/
  int flag = 1;
  int result = setsockopt(s,            /* socket affected */
			  IPPROTO_TCP,     /* set option at TCP level */
			  TCP_NODELAY,     /* name of option */
			  (char *) &flag,  /* the cast is historical
					      cruft */
			  sizeof(int));    /* length of option value */
  if (result < 0){
    mexErrMsgTxt("setsockopt() failed");
  }
	    
  /***********************************************/
  /* connect socket to given address */
  /***********************************************/
  struct sockaddr_in peeraddr_in;
  memset(&peeraddr_in, 0, sizeof(struct sockaddr_in));  
  peeraddr_in.sin_addr.s_addr = inet_addr(ipAddressArgument);
  peeraddr_in.sin_family = AF_INET;
  peeraddr_in.sin_port = htons((unsigned short)SCPI_PORT);
  
  if (connect(s, (const struct sockaddr*)&peeraddr_in,
	      sizeof(struct sockaddr_in)) == SOCKET_ERROR){ 
    mexErrMsgTxt("connect(): SOCKET_ERROR");
  }
  
  /***********************************************/
  /* copy socket into char[] array and return */
  /***********************************************/
  mxArray* out;
#define NDIM (2)
  int dim[NDIM];
  dim[0] = 1;
  dim[1] = (int)sizeof(SOCKET);
  out = mxCreateCharArray(NDIM, dim);
  memcpy(/* dest */mxGetChars(out), /* source */ (void*)&s, sizeof(SOCKET));
  plhs[0] = out;
}
