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

network_glue.cc

using namespace std;

#include <iostream> 
#include <VMState.h>
#include "network_glue.h"

#include <gc/gc.h>
#include <unistd.h>
#include <fcntl.h>

#ifdef WIN32
#define SHUT_RDWR SD_BOTH
#endif

// this function does nothing on Unix but should be called anyway
// for compatibility.
void net_init(void* vmptr) {
#ifdef WIN32
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;
 
  wVersionRequested = MAKEWORD( 2, 0 );
 
  err = WSAStartup( wVersionRequested, &wsaData );
  if ( err != 0 ) {
    VMState* vm = (VMState*)vmptr;
    vm->kaya_throw("Couldn't initialise network library",1);
  }
#endif
}

/// Create a socket and connect to the server. Returns connection info.
void* net_connect(void* vmptr, int proto,wchar_t* rawserver, int port)
{
  char* server = CSTRING(rawserver);
    VMState* vm = (VMState*)vmptr;
    int sock;
    struct sockaddr_in addr;

    switch(proto) {
    case 1: 
      sock=socket(PF_INET,SOCK_STREAM,0);
      addr.sin_family=AF_INET;
      break;
//    case 2:
//    sock=socket(PF_INET6,SOCK_STREAM,0);
//    addr.sin_family=AF_INET6;
//    break;
    default:
      vm->kaya_throw("Protocol not supported (yet)",1);
    }

    struct hostent * hostinfo;
    hostinfo=gethostbyname(server);
    if (hostinfo==NULL)
    {
#ifdef WIN32
      vm->kaya_throw("Can't get host address!",WSAGetLastError());
#else
      vm->kaya_throw("Can't get host address!",1);
#endif
    }
    addr.sin_addr=*(struct in_addr *)hostinfo->h_addr;
    addr.sin_port=htons(port);

    if (connect(sock,(struct sockaddr *)(&addr),sizeof(struct sockaddr_in))==-1)
    {
      vm->kaya_throw("Error in connecting",1);
    }

    ConnInfo *c = new ConnInfo();
    c->cid = sock;
    c->addr = addr;
    c->addrlen = sizeof(struct sockaddr_in);

    // Make it non blocking
//    fcntl(sock,F_SETFL,O_NONBLOCK);
    return (void*)c;
}

/// Create a socket and start listening. Returns socket id.
int net_listen(void* vmptr,int proto, int port, int backlog)
{
    VMState* vm = (VMState*)vmptr;
    int sock;
    struct sockaddr_in name;

    switch(proto) {
    case 1: 
      sock=socket(PF_INET,SOCK_STREAM,getprotobyname("tcp")->p_proto);
      name.sin_family = AF_INET;
      break;
//    case 2:
//    sock=socket(PF_INET6,SOCK_STREAM,getprotobyname("tcp")->p_proto);
//    name.sin_family = AF_INET6;
//    break;
    default:
      vm->kaya_throw("Protocol not supported (yet)",1);
    }

#ifdef WIN32
    BOOL val=TRUE;
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&val,sizeof(int));
#else
    int val=1;
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(int));
#endif

    name.sin_port = htons(port);
    name.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sock,(struct sockaddr *)(&name),sizeof(struct sockaddr_in)))
    {
      vm->kaya_throw("Can't bind to port",1);
    }

    if (listen(sock,backlog))
    {
      vm->kaya_throw("Can't listen",1);
    }

    return sock;
}

/// Accept a connection. Returns connection info.
void* net_accept(void* vmptr,int socket)
{
    VMState* vm = (VMState*)vmptr;
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr_in);

    int client = accept(socket,(struct sockaddr *)&addr,&len);
    if (client==-1) {
      vm->kaya_throw("Accept failed",1);
    }
    
    ConnInfo *c = new ConnInfo();
    c->cid = client;
    c->addr = addr;
    c->addrlen = len;
    return (void*)c;
}

/// Shutdown a connection.
void net_shutdown(void* conn)
{
    ConnInfo* c = (ConnInfo*)conn;
    shutdown(c->cid, SHUT_RDWR);
}

/// Close a socket.
void net_close(void* conn)
{
    ConnInfo* c = (ConnInfo*)conn;
    close(c->cid);
}


void net_send(void* vmptr,void* conn, wchar_t* rawdata)
{
  char* data = CSTRING(rawdata);
    VMState* vm = (VMState*)vmptr;
    ConnInfo* c = (ConnInfo*)conn;
    int rlen;

    do {
        rlen = send(c->cid, data,strlen(data),0);
    } while (errno == EINTR);
    if (rlen<0) {
      vm->kaya_throw("send failed",1);
    }
}

char* net_recv(void* vmptr,void* conn, KayaValue len)
{
    VMState* vm = (VMState*)vmptr;
    ConnInfo* c = (ConnInfo*)conn;
    int lenval = KayaGetInt(len);
    char* buf = (char*)GC_MALLOC((lenval+1)*sizeof(char*));
    int rlen;
    do {
        rlen = recv(c->cid, buf,lenval,0);
    } while (errno == EINTR);
    KayaSetInt(len,rlen);
    if (rlen<0) {
//    cout << rlen << endl;
//    buf[0]='\0';
      vm->kaya_throw("nothing to receive",1);
    }
    return buf;
}

char* net_getaddr(void* conn)
{
    ConnInfo* c = (ConnInfo*)conn;
    struct in_addr addr = c->addr.sin_addr;

    char* h = inet_ntoa(addr);

    int len = strlen(h);
    char* host = (char*)GC_MALLOC((len+1)*sizeof(char*));
    strcpy(host,h);

    return host;
}

bool net_pending(void* vmptr,void* conn, int timeout)
{
    VMState* vm = (VMState*)vmptr;
    ConnInfo* c = (ConnInfo*)conn;
    fd_set rfds;
    struct timeval tv;
    FD_ZERO(&rfds);
    FD_SET(c->cid,&rfds);
    tv.tv_sec = timeout/1000000;
    tv.tv_usec = timeout%1000000;

    int rv;
    do {
        rv = select(c->cid+1,&rfds,NULL,NULL,&tv);
    } while (errno == EINTR);

    if (rv==-1) {
      vm->kaya_throw("select() error",1); 
    }
    else {
      return rv;
    }
}


Generated by  Doxygen 1.6.0   Back to index