/******************************************************************************
* $Id: socketcommon.c,v 1.6 2006/01/13 23:01:49 gareuselesinge Exp $
* This file is part of liberopops (http://liberopops.sf.net) *
* This file is distributed under the terms of GNU GPL license. *
******************************************************************************/
/******************************************************************************
* File description:
* wrap functions for sockets
* Notes:
* based on altsocklib.[ch]
* Authors:
* Enrico Tassi <gareuselesinge@users.sourceforge.net>
******************************************************************************/
#if defined(WIN32) && !defined(CYGWIN)
#include <winsock.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "socketcommon.h"
#include "win32_compatibility.h"
#include "log.h"
#define LOG_ZONE "socketcommon"
struct sock_state_t
{
//! the socket handler
int socket;
//! hostname
char *hostname;
//! string with the IP in xxx.xxx.xxx.xxx form
char *ipaddress;
//! real port
unsigned long realport;
//! buffer for altsocklib
recvbuffer_t *prb;
//! function used for debug printing
void (*print)(char *);
//! flag used to inhibit commands
int error_occurred;
//! line len
int maxlinelen;
};
/************************** output functions ****************************/
static void sock_print(const char *prebuffer,const char *buffer,
struct sock_state_t *s)
{
char tmp[s->maxlinelen];
snprintf(tmp,s->maxlinelen,"%s%s\n",prebuffer,buffer);
s->print(tmp);
}
static void sock_error(char *type,int ernum,struct sock_state_t *s)
{
char tmp[s->maxlinelen];
strncpy(tmp,SOCK_ERROR,s->maxlinelen);
strncat(tmp,type,s->maxlinelen);
snprintf(tmp,s->maxlinelen,"Error calling \"%s\" (code %d - %s)",
type,ernum,strerror(errno));
sock_print(SOCK_ERROR,tmp,s);
s->error_occurred=1;
}
static void sock_received(char *buffer,struct sock_state_t *s)
{
sock_print(SOCK_RECEIVED,buffer,s);
}
static void sock_sent(const char *buffer,struct sock_state_t *s)
{
sock_print(SOCK_SENT,buffer,s);
}
static void sock_info(char *buffer,struct sock_state_t *s)
{
sock_print(SOCK_INFO,buffer,s);
}
int sock_error_occurred(struct sock_state_t *s){
return s->error_occurred;
}
/***************************** SEND /RECIVED checked **********************/
#define SKIP(s,a...) \
else {\
char tmp[s->maxlinelen];\
snprintf(tmp,s -> maxlinelen,\
"A previous error occurred, skipping : " a);\
sock_info(tmp,s);\
return -1;\
}
int sock_send(struct sock_state_t *s,char* buffer)
{
int rc;
if ( s != NULL && ! s->error_occurred )
{
if ( (rc=sendstring(s->socket, buffer)) < 0 )
sock_error("sendstring",rc,s);
else sock_sent(buffer,s);
return 0;
}
SKIP(s,"sock_send(\"%s\")",buffer);
}
int sock_sendraw(struct sock_state_t *s,const char* buffer)
{
int rc;
if ( s != NULL && ! s->error_occurred )
{
if ( (rc=sendstring_raw(s->socket, buffer)) < 0 )
sock_error("sendstring",rc,s);
else sock_sent(buffer,s);
return 0;
}
SKIP(s,"sock_sendraw(\"%s\")",buffer);
}
int sock_receive(struct sock_state_t *s,char* buffer,int maxlen)
{
if ( ! s->error_occurred)
{
int tmp = recvstring( s->socket, buffer, maxlen , s->prb);
if ( tmp < 0 )
sock_error("recvstring",tmp,s);
else
sock_received(buffer,s);
return tmp;
}
SKIP(s,"sock_receive");
}
int sock_receive_with_timeout(struct sock_state_t *s,char* buffer,
int maxlen, int timeout)
{
if ( ! s->error_occurred)
{
int tmp = recvstring_with_timeout(s->socket,buffer,
maxlen,s->prb,timeout);
if ( tmp == -2 )
sock_error("recvstring_with_timeout timeout",tmp,s);
else if ( tmp == -1 )
sock_error("recvstring_with_timeout error",tmp,s);
else {
sock_received(buffer,s);
}
return tmp;
}
SKIP(s,"sock_receive");
}
static void get_info(struct sock_state_t* tmp)
{
unsigned char info[6];
// get server infos
if ( sockinfo(tmp->socket, info)== -1 ) sock_error("sockinfo",-1,tmp);
snprintf( tmp->ipaddress, strlen("255.255.255.255") + 1,
"%d.%d.%d.%d" , info[0], info[1], info[2], info[3] );
tmp->realport = info[4] * 256 + info[5] ;
}
/*********************** connect *********************************************/
struct sock_state_t * sock_connect(char *hostname,
unsigned long port,int maxlinelen,void (*print)(char *))
{
struct sock_state_t *tmp;
#if !(defined(WIN32) && !defined(CYGWIN) || defined(__sun))
struct in_addr anyaddress = { INADDR_ANY };
#else
struct in_addr anyaddress = {{{ INADDR_ANY }}};
#endif
char infostring[]="Ip address xxx.xxx.xxx.xxx real port xxxxx";
tmp = (struct sock_state_t *) malloc(sizeof(struct sock_state_t));
if(tmp == NULL)
return NULL;
tmp->maxlinelen = maxlinelen;
tmp->hostname = strdup(hostname);
tmp->ipaddress = strdup("255.255.255.255");
tmp->prb = recvBufferCreate(maxlinelen); // maybe too long ??
tmp->print = print; // print function
tmp->error_occurred = 0; // no errors
// CREATE SOCKET
if ( ( tmp->socket = sockopen( hostname , anyaddress , port ) ) == -1 )
{
sock_error("sockopen",-1,tmp);
}
// get server infos
get_info(tmp);
sprintf(infostring,"Ip address %s real port %ld",tmp->ipaddress,tmp->realport);
sock_info(infostring,tmp);
return(tmp);
}
void sock_disconnect(struct sock_state_t *server)
{
if ( sockclose( server->socket ) == -1 )
sock_error("socketclose",-1,server);
recvBufferDestroy(server->prb);
free(server->ipaddress);
free(server->hostname);
free(server);
}
struct sock_state_t * sock_bind(struct in_addr bind_add, unsigned short port,
int maxlinelen,void (*print)(char *))
{
struct sock_state_t *tmp;
char infostring[]="Ip address xxx.xxx.xxx.xxx real port xxxxx";
tmp = (struct sock_state_t *) malloc(sizeof(struct sock_state_t));
if(tmp == NULL)
return NULL;
tmp->maxlinelen = maxlinelen;
tmp->hostname = strdup("localhost");
tmp->ipaddress = strdup("255.255.255.255");
tmp->prb = recvBufferCreate(maxlinelen); // maybe too long ??
tmp->print = print; // print function
tmp->error_occurred = 0; // no errors
// CREATE SOCKET
tmp->socket = sockopen( NULL , bind_add , port);
if ( tmp->socket == -1 )
{
sock_error("sockopen",-1,tmp);
fprintf(stderr,"Unable to bind on %s:%u\n",inet_ntoa(bind_add),port);
free(tmp);
exit(1);
}
//GET INFOS
get_info(tmp);
sprintf(infostring,"Ip address %s real port %ld",tmp->ipaddress,tmp->realport);
sock_info(infostring,tmp);
//listen
if (listen(tmp->socket, 5) == -1) {
sockerror("socklisten(listen)");
exit(0);
}
return (tmp);
}
struct sock_state_t * sock_listen(struct sock_state_t * s)
{
struct sockaddr sockaddr;
unsigned int addrlen = sizeof(sockaddr);
int newsock;
memset(&sockaddr, 0, sizeof(sockaddr));
newsock = accept(s->socket, &sockaddr, &addrlen);
if (newsock != -1)
{
struct sock_state_t* tmp;
char infostring[]="Ip address xxx.xxx.xxx.xxx real port xxxxx";
//create the new Servet_State_t
tmp = (struct sock_state_t *)
malloc(sizeof(struct sock_state_t));
MALLOC_CHECK(tmp);
tmp->maxlinelen = s->maxlinelen;
tmp->hostname = strdup("localhost");
tmp->ipaddress = strdup("255.255.255.255");
tmp->prb = recvBufferCreate(tmp->maxlinelen);
tmp->print = s->print; // print function
tmp->error_occurred = 0; // no errors
tmp->socket = newsock;
get_info(tmp);
sprintf(infostring,"Ip address %s real port %ld",
tmp->ipaddress,tmp->realport);
sock_info(infostring,tmp);
return tmp;
}
else {
sockerror("socklisten(accept)");
return NULL;
}
}
syntax highlighted by Code2HTML, v. 0.9.1