Your problem in 1 was probably winsock startup code.... or maybe something with nonblocking sockets, however I'm thinking the first. Check out the code I've attached, and try running psocket_environment_init(). The code may be re-licensned to GPL if you wish...... Your welcome to butcher that code out of there; and you'll probably want to change the formatting.

As for user home directories, that just takes a little looking up some registry keys on Microsoft.com...... I'll look into it


I have a HTTP server project which is kinda old (khd.sf.net), and it had a small libglade interface; Which I got working on Win32. It included socketpair and pthreads; and worked fine on windows. You should E-mail what you have, to see if I can't get it working.


in response to E Roberts:
Hi,

On a couple of different occasions I have attempted to make a gtkg win32
build.  The last time I got it compiling and running but I must have
done something wrong with the win32 networking/sockets api because I
could never connect to anything.  I was going to clean up my code and
submit it so people could at least have a base in the future, but I
never got around to doing that.

It's something that has been sort of in the back of my mind forever but
I never get around to doing it :)  Anyway, I am not sure how far along
Jeroen is but I thought I mention a couple of things that I got stuck
on, maybe they will help someone.

1. Files - all the file accesses we use should be converted to glib
functions if they aren't already.  Glib automatically converts unix
style directory names to win32 but I remember there being a problem with
home directories and file creation, etc.  I am pretty sure I just
converted all the unix style fopen, etc. calls to the glib equivalents.

2. Resources - all the functions in resource.h weren't ported to mingw
(and probably still aren't).  I actually just commented out these
calls/hacked up static values for available memory/etc. and "was going
to deal with it later".  I think we might be able to do this properly
with the win32 API, but I am not sure if all of the API is available
under mingw.  Anyway, this is where we need to look (unless someone in
the wide world has done a mingw resource.h library already).

3. Networking - there are no glib functions for networking (quel
dommage!).  There are mingw/win32 API functions equivalent to the unix
socket functions but as I remember they have different function
parameters.  This means a bunch of "#ifndef _MINGW_W32_"'s with
alternative calls to socket functions.  Also, on W32 before your
application can actually use any sockets, you need to call a socket
initializing function.  WSAStartup I think.

The good news is that aside from these three things, things were easy to
get working.  The GUI was fine and the non-networking part of the
backend (which is unfortunately not much of it) seemed to be
operational.  I should have kept at it or sent it in because I am sure
the only problem was my dismal attempt at windows sockets.

I've done a few cross-platform apps in gtk now though, maybe I should
try it again...  In any case, I hope this helps you out somewhat.  Good
luck!

Emilie



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Gtk-gnutella-devel mailing list
Gtk-gnutella-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gtk-gnutella-devel


/*
 *  FILE: 
 *  	portable_socket.c
 *
 *  DESCRIPTION:
 *  	Set of functions dealing with socket initialization, read/writes, or
 *      even socket creation on Win32.  You may choose use OpenSSL or BSD sockets.
 *
 *  FUNCTIONS:
 *      socketpair()  - Very simple rewrite of socketpair on Win32 for 
 *                      AF_LOCAL/SOCK_STREAM connection, with no options.
 *                      Call socket_init() if problems with binary data occur. 
 *      socket_init()  -SIGPIPE ignore for *n*x, and winsock/_fmode stuff on Windows.
 *                      Please Note: this function on windows changes all pipes to binary.
 *  	readline_r()  - Reentrant readline function with support for CRLF, 
 *                      or just CR.
 *  	fullsend()    - Write data without worrying about all of it being written.  
 *                      Useful for sockets.
 * 
 *
 * Copyright (c) 2004-2006 Karlan Thomas Mitchell<[EMAIL PROTECTED]>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, is prohibited except by
 * Karlan Thomas Mitchell.
 *
 * THIS SOFTWARE IS PROVIDED BY KARLAN THOMAS MITCHELL AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/
#include "portable_socket.h"



int sock_nonblock(int sock){
#ifdef __WIN32__
	unsigned long cmd = 1;
	if ( ioctlsocket(sock, FIONBIO, &cmd)  <  0 ){
		perror("socketioctl");
		return -1;
		}
#else
	int cmd = fcntl(sock, F_GETFL);
	if ( cmd < 0 ){
		perror("fcntl");
		return -1;
		}
	if ( fcntl(sock, F_SETFL, cmd | O_NONBLOCK) < 0 ){
		perror("fcntl");
		return -1;
		}
#endif
	return 0;
}


#ifdef __WIN32__
#ifndef __CYGWIN__




int socketpair(int domain, int type, int protocol, int sv[2]){

    if(protocol != 0){
	errno = EINVAL;
	return -1;
	}
    if(type != SOCK_STREAM){
	errno = EINVAL;
	return -1;
	}
    if(domain != AF_LOCAL){
	errno = EINVAL;
	return -1;
	}

    return _pipe(sv, 4096, _O_BINARY );
}


#endif /*!CYGWIN*/
#endif /*Win32*/



int psocket_environment_init(){
	
	#ifdef USE_OPENSSL
	/* Initializing OpenSSL */
	SSL_load_error_strings();
	ERR_load_BIO_strings();
	OpenSSL_add_all_algorithms();
	#endif


	#ifndef __WIN32__
	/*UNIX*/
	/*Don't kill program on SIGPIPE!*/
	signal(SIGPIPE, SIG_IGN);

	
	#else
	/*Microsoft Windows Code: */

	/*for socketpair*/
       _fmode = _O_BINARY;
       WSADATA wsaData; 

	/*Winsock*/
       if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
              fprintf(stderr, "WSAStartup failed.\n");
              return -1;
       } 
	#endif
	return 0;
}





#ifdef USE_OPENSSL

ssize_t BIO_readline_r(BIO * bio, char * buffer, ssize_t bufferlen){
	if(bufferlen <= 0)
		return -1;
	ssize_t dataread = 0;
	char * tc = (char *)malloc(1 * sizeof(char));
	int rv;
	char lastchar = 0;
	for( ;  ;dataread++ ){
        rv = BIO_read(bio, tc, 1);
        if(rv <= 0){
               printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
 	      break;
          }
		if(tc[0] == '\x0A'){
			if(lastchar == '\x0D')
				dataread--;
			break;
		}
		if(dataread >= bufferlen - 1)/*Discard Data...*/
			continue;
		buffer[dataread] = tc[0];
		lastchar = tc[0];
	}	

	/*if we didn't fill the entire buffer, null it for the programmer*/
	if(dataread <= bufferlen - 1)
		buffer[dataread] = 0;

	free(tc);

	if(rv <= 0)
		return rv;
	return dataread;
}


ssize_t BIO_fullsend(BIO *  bio, char * buffer, ssize_t buflen){
	if(buflen <= 0)
		return -1;
	ssize_t left = buflen;
	ssize_t sent;
	char * sendpnt= &(buffer[0]);
	
	while(left > 0){
		sent = BIO_write(bio, sendpnt, left);
		if(sent <= 0)
			return sent;
		sendpnt = &(sendpnt[sent]);
		left -= sent;
	}
	return buflen - left;
}

#endif



/*WARNING: If the buffer is too small, data is read up to newline [sequence],
           and data after the size of the buffer is discarded*/
/*NOTE: supports \r\n or \n, not just \r*/
/* NOTE: return of zero is empty line */
ssize_t readline_r(int fd, char * buffer, ssize_t bufferlen, int read_socket){
	if(bufferlen <= 0)
		return -1;
	ssize_t dataread = 0;
	char * tc = (char *)malloc(1 * sizeof(char));
	int rv;
	char lastchar = 0;
	for( ;  ;dataread++ ){
        	if(read_socket)
		   	rv = recv(fd, tc, 1, 0);
        	else
	   	   	rv = read(fd, tc, 1);
        	 if(rv <= 0){
               		if(read_socket == 0)
                 		perror("read");
               		/*WINSOCK has non standard error return for recv*/
 	      		break;
          		}
		if(tc[0] == '\x0A'){
			if(lastchar == '\x0D')
				dataread--;
			break;
		}
		if(dataread >= bufferlen - 1)/*Discard Data...*/
			continue;
		buffer[dataread] = tc[0];
		lastchar = tc[0];
	}	

	/*if we didn't fill the entire buffer, null it for the programmer*/
	if(dataread <= bufferlen - 1)
		buffer[dataread] = 0;

	free(tc);

	if(rv <= 0)
		return rv;

	return dataread;
}

ssize_t readline_r_timeout(int fd, char * buffer, ssize_t bufferlen, int read_socket, struct st_timeval * time_data){
	if(time_data == NULL)
		return readline_r(fd, buffer, bufferlen, read_socket);

	time_t start_time = time(NULL);
	time_t curr_time;
	ssize_t return_val;	
	int tmp_errno = errno;

	if(bufferlen <= 0)
		return -1;

	ssize_t dataread = 0;
	char * tc = (char *)malloc(1 * sizeof(char));
	int rv;
	char lastchar = 0;
	int function_return_val = 0;


	for( ;  ;dataread++ ){
 		curr_time = time(NULL);
 		if(curr_time - start_time >= time_data->tv_sec)
 				break;

        	if(read_socket)
		   	rv = recv(fd, tc, 1, 0);
        	else
	   	   	rv = read(fd, tc, 1);
		

		if(rv == 0){
			function_return_val = -1;
			break;
			}

		if(rv < 0){
			tmp_errno = errno;
			usleep(250000); /*1 quarter of a second*/ 
			dataread--;
			continue;
			}

		if(tc[0] == '\x0A'){
			if(lastchar == '\x0D')
				dataread--;
			break;
		}
		if(dataread >= bufferlen - 1)/*Discard Data...*/
			continue;
		buffer[dataread] = tc[0];
		lastchar = tc[0];

	}	

	/*if we didn't fill the entire buffer, null it for the programmer*/
	if(dataread <= bufferlen - 1)
		buffer[dataread] = 0;

	free(tc);


	curr_time = time(NULL);
	time_data->tv_sec = time_data->tv_sec - (curr_time - start_time);

	errno = tmp_errno;
	if(function_return_val == -1)
		return function_return_val;
	return dataread;
}




/*WARNING: THIS FUNCTION SENDS UP TO *(buffer+buflen), zero stops nothing!
  NOTE: The reason for above: the ability to send binary data*/
ssize_t fullsend(int socketd, char * buffer, ssize_t buflen){
	if(buflen <= 0)
		return -1;
	ssize_t left = buflen;
	ssize_t sent;
	char * sendpnt= &(buffer[0]);
	
	while(left > 0){
		sent = write(socketd, sendpnt, left);
		if(sent <= 0)
			return sent;
		sendpnt = &(sendpnt[sent]);
		left -= sent;
	}
	return buflen - left;
}


ssize_t portable_setnonblock(struct st_psocket * portable_data){
	if(portable_data->io_method == IO_BSD){
		return sock_nonblock(portable_data->io_data.bsd_io.clientfd);
	}
	else
		return -1;
}
ssize_t portable_read_timeout(struct st_psocket * portable_data, char * buffer, size_t bufferlen, struct st_timeval * time_data){
	if(time_data == NULL)
		return portable_read(portable_data, buffer, bufferlen);

	time_t start_time = time(NULL);
	time_t curr_time = start_time;
	ssize_t return_val;	
	int tmp_errno;

	if(portable_data->io_method == IO_BSD){
		while(curr_time - start_time < time_data->tv_sec){
		return_val = recv(portable_data->io_data.bsd_io.clientfd, buffer, bufferlen, 0);
		if(return_val > 0){
			curr_time = time(NULL);
			time_data->tv_sec = time_data->tv_sec - (curr_time - start_time);
			return return_val;
			}
		if(return_val == 0){
			errno = tmp_errno;
			}
		if(return_val < 0)
			break;
		
		usleep(250000); /*1 quarter of a second*/ 
		curr_time = time(NULL);
		}
	}
	else
		return -1;

	time_data->tv_sec = time_data->tv_sec - (curr_time - start_time);
	errno = tmp_errno;
	return -1;
}


ssize_t portable_write_timeout(struct st_psocket * portable_data, char * buffer, size_t bufferlen, struct st_timeval * time_data){
	if(time_data == NULL)
		return portable_write(portable_data, buffer, bufferlen);

	time_t start_time = time(NULL);
	time_t curr_time  = start_time;
	ssize_t return_val;	
	int tmp_errno;

	if(portable_data->io_method == IO_BSD){
		while(curr_time - start_time < time_data->tv_sec){
		return_val = write(portable_data->io_data.bsd_io.clientfd, buffer, bufferlen);
		if(return_val > 0){
			curr_time = time(NULL);
			time_data->tv_sec = time_data->tv_sec - (curr_time - start_time);
			return return_val;
			}
		if(return_val == 0){
			errno = tmp_errno;
			}
		if(return_val < 0)
			break;

		usleep(250000); /*1 quarter of a second*/ 
		curr_time = time(NULL);
		}
	}
	else
		return -1;

	time_data->tv_sec = 0;
	tmp_errno = errno;
	return -1;
}

ssize_t portable_readline_timeout(struct st_psocket * psocket_data, char * buffer, ssize_t bufferlen, struct st_timeval * time_data){

	if(psocket_data->io_method == IO_BSD){
		return readline_r_timeout(psocket_data->io_data.bsd_io.clientfd, buffer, bufferlen, 1, time_data);
	}
	else
		return -1;
	return -1;
}


/*Wrappers to make OpenSSL/Native HTTP IO transparent more opaque*/
ssize_t portable_read(struct st_psocket * portable_data, char * buffer, size_t bufferlen){
	if(portable_data->io_method == IO_BSD){
		return recv(portable_data->io_data.bsd_io.clientfd, buffer, bufferlen, 0);
	}
	#ifdef USE_OPENSSL
	else if(portable_data->io_method == IO_OPENSSL){
		return BIO_read(portable_data->io_data.openssl_io.bio, buffer, bufferlen);
	}
	#endif
	else
		return -1;
}



ssize_t portable_write(struct st_psocket * psocket_data, char * buffer, size_t bufferlen){
	if(psocket_data->io_method == IO_BSD){
		return write(psocket_data->io_data.bsd_io.clientfd, buffer, bufferlen);
	}
	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		return BIO_write(psocket_data->io_data.openssl_io.bio, buffer, bufferlen);
	}
	#endif
	else
		return -1;
}

ssize_t portable_readline_r(struct st_psocket * psocket_data, char * buffer, ssize_t bufferlen){
	if(psocket_data->io_method == IO_BSD){
		return readline_r(psocket_data->io_data.bsd_io.clientfd, buffer, bufferlen, 1);
	}
	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		return BIO_readline_r(psocket_data->io_data.openssl_io.bio, buffer, bufferlen);
	}
	#endif
	else
		return -1;
}
ssize_t portable_fullsend(struct st_psocket * psocket_data, char * buffer, ssize_t bufferlen){
	if(psocket_data->io_method == IO_BSD){
		return fullsend(psocket_data->io_data.bsd_io.clientfd, buffer, bufferlen);
	}
	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		return BIO_fullsend(psocket_data->io_data.openssl_io.bio, buffer, bufferlen);
	}
	#endif
	else
		return -1;
}





char * portable_get_client_ip(struct st_psocket * psocket_data){
	if(psocket_data->io_method == IO_BSD){
		return inet_ntoa(psocket_data->io_data.bsd_io.clientaddr.sin_addr);
	}
	else
		return NULL;
}


#ifdef USE_OPENSSL

int portable_ssl_bind(struct st_psocket * psocket_data, char * address, int short unsigned port, char * pem){

	psocket_data->io_method = IO_OPENSSL;


        psocket_data->io_data.openssl_io.ctx = SSL_CTX_new(SSLv23_server_method());

 	if (!SSL_CTX_use_certificate_file( psocket_data->io_data.openssl_io.ctx,pem,SSL_FILETYPE_PEM)
            || !SSL_CTX_use_PrivateKey_file(psocket_data->io_data.openssl_io.ctx,pem,SSL_FILETYPE_PEM)
            || !SSL_CTX_check_private_key(psocket_data->io_data.openssl_io.ctx)) {

       		 fprintf(stderr, "Error setting up SSL_CTX\n");
       		 ERR_print_errors_fp(stderr);
       		 return -1;
 	}

 	/* New SSL BIO setup as server */
 	psocket_data->io_data.openssl_io.sbio = BIO_new_ssl(psocket_data->io_data.openssl_io.ctx,0);

 	BIO_get_ssl(psocket_data->io_data.openssl_io.sbio, &psocket_data->io_data.openssl_io.ssl);

 	if(!psocket_data->io_data.openssl_io.ssl) {
   		fprintf(stderr, "Can't locate SSL pointer\n");
   		/* whatever ... */
 	}

 	/* Don't want any retries */
 	SSL_set_mode(psocket_data->io_data.openssl_io.ssl, SSL_MODE_AUTO_RETRY);



	char * port_str = malloc(20 * sizeof(char));
	snprintf(port_str, 20, "%d", port);

        psocket_data->io_data.openssl_io.bio = BIO_new_accept(port_str);
	
	free(port_str);


	 BIO_set_accept_bios(psocket_data->io_data.openssl_io.bio,psocket_data->io_data.openssl_io.sbio);

        /* First call to BIO_accept() sets up accept BIO */
        if(BIO_do_accept( psocket_data->io_data.openssl_io.bio) <= 0) {
//                fprintf(stderr, "Error setting up accept\n");
//                ERR_print_errors_fp(stderr);
               return -1;
        }
	return 0;
}

#endif


int portable_bind(struct st_psocket * psocket_data, char * address, int short unsigned port){

	psocket_data->io_method = IO_BSD;

	if( (psocket_data->io_data.bsd_io.serverfd = socket(AF_INET, SOCK_STREAM,0)) == -1 ){
			fprintf(stderr, "portable_bind * socket() Error!\n");
			perror("socket");
			return -1;
	}
		
	psocket_data->io_data.bsd_io.serveraddr.sin_family = AF_INET;     
	psocket_data->io_data.bsd_io.serveraddr.sin_port = htons(port);  
	psocket_data->io_data.bsd_io.serveraddr.sin_addr.s_addr = inet_addr(address);
	memset(&(psocket_data->io_data.bsd_io.serveraddr.sin_zero), '\0', 8);
	
	if(bind(psocket_data->io_data.bsd_io.serverfd, (struct sockaddr *)&psocket_data->io_data.bsd_io.serveraddr, sizeof(struct sockaddr))  == -1){
			fprintf(stderr, "portable_bind * bind() Error!\n");
			perror("bind");
			closesocket(psocket_data->io_data.bsd_io.serverfd);
			return -1;
	}

	
	if (listen(psocket_data->io_data.bsd_io.serverfd, 20) == -1) {
			fprintf(stderr, "portable_bind * listen() Error!\n");
            		perror("listen");
			closesocket(psocket_data->io_data.bsd_io.serverfd);
			return -1;
        }
	return 0;
}


#ifdef USE_OPENSSL

int portable_set_openssl(struct st_psocket * psocket_data, char * pem){
	int clientfd = psocket_data->io_data.bsd_io.clientfd;
	psocket_data->io_method = IO_OPENSSL;

        psocket_data->io_data.openssl_io.ctx = SSL_CTX_new(SSLv23_server_method());

 	if (!SSL_CTX_use_certificate_file( psocket_data->io_data.openssl_io.ctx,pem,SSL_FILETYPE_PEM)
            || !SSL_CTX_use_PrivateKey_file(psocket_data->io_data.openssl_io.ctx,pem,SSL_FILETYPE_PEM)
            || !SSL_CTX_check_private_key(psocket_data->io_data.openssl_io.ctx)) {

       		 fprintf(stderr, "Error setting up SSL_CTX\n");
       		 ERR_print_errors_fp(stderr);
       		 return -1;
 	}

 	/* New SSL BIO setup as server */
 	psocket_data->io_data.openssl_io.sbio = BIO_new_ssl(psocket_data->io_data.openssl_io.ctx,0);

 	BIO_get_ssl(psocket_data->io_data.openssl_io.sbio, &psocket_data->io_data.openssl_io.ssl);
 	SSL_set_fd(psocket_data->io_data.openssl_io.ssl, clientfd);

 	if(!psocket_data->io_data.openssl_io.ssl) {
   		fprintf(stderr, "Can't locate SSL pointer\n");
   		/* whatever ... */
 	}

 	/* Don't want any retries */
 	SSL_set_mode(psocket_data->io_data.openssl_io.ssl, SSL_MODE_AUTO_RETRY);
 	psocket_data->io_data.openssl_io.bio = psocket_data->io_data.openssl_io.sbio;

	return 0;
}

#endif

int portable_copy(struct st_psocket * new_psocket, struct st_psocket * old_psocket){

        new_psocket->io_method  = old_psocket->io_method;
	memcpy(new_psocket, old_psocket, sizeof(struct st_psocket));

	#ifdef USE_OPENSSL
	if(new_psocket->io_method == IO_OPENSSL)
        	new_psocket->io_data.openssl_io.bio  = BIO_pop(old_psocket->io_data.openssl_io.bio);
	#endif

	return 0;
}

int portable_accept(struct st_psocket * psocket_data){
	if(psocket_data->io_method == IO_BSD){
	socklen_t sin_size = sizeof(struct sockaddr_in);
		if (   (psocket_data->io_data.bsd_io.clientfd = accept(psocket_data->io_data.bsd_io.serverfd, (struct sockaddr *)&psocket_data->io_data.bsd_io.clientaddr, &sin_size)) == -1) {
                	perror("accept");
                	return -1;
		}
	}

	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		if(BIO_do_accept( psocket_data->io_data.openssl_io.bio) <= 0) {
			fprintf(stderr, "Error setting up accept\n");
			ERR_print_errors_fp(stderr);
               		return -1;
        	}
	}
	#endif	

	return 0;
}

int portable_connect(struct st_psocket * psocket_data, char * host, int unsigned short port){
	if(psocket_data->io_method == IO_BSD){
		if( (psocket_data->io_data.bsd_io.clientfd = socket(AF_INET, SOCK_STREAM,0)) == -1 ){
			fprintf(stderr, "portable_connect * socket() Error!\n");
			perror("socket");
			return -1;
		}       
		psocket_data->io_data.bsd_io.clientaddr.sin_family = AF_INET;        /* host byte order */
        	psocket_data->io_data.bsd_io.clientaddr.sin_port = htons(port); /* short, network byte order */
       		psocket_data->io_data.bsd_io.clientaddr.sin_addr.s_addr = inet_addr(host);
        	bzero(&(psocket_data->io_data.bsd_io.clientaddr.sin_zero), 8);       /* zero the rest of the struct */
		if( connect(psocket_data->io_data.bsd_io.clientfd, (struct sockaddr *)&psocket_data->io_data.bsd_io.clientaddr, sizeof(struct sockaddr)) == -1 ){
			fprintf(stderr, "portable_connect * connect() Error!\n");
			perror("connect");
			return -1;
		}
	}

	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		psocket_data->io_data.openssl_io.ctx = SSL_CTX_new(SSLv23_client_method());
/*
 		if (!SSL_CTX_check_private_key(psocket_data->io_data.openssl_io.ctx)) {
			fprintf(stderr, "Error setting up SSL_CTX\n");
			ERR_print_errors_fp(stderr);
			return -1;
		}*/

        	psocket_data->io_data.openssl_io.sbio = BIO_new_ssl_connect(psocket_data->io_data.openssl_io.ctx);

        	BIO_get_ssl(psocket_data->io_data.openssl_io.sbio, &psocket_data->io_data.openssl_io.ssl);

        	if(!psocket_data->io_data.openssl_io.ssl) {
			fprintf(stderr, "Can't locate SSL pointer\n");
			return -1;
        	}

        	/* Don't want any retries */
		SSL_set_mode(psocket_data->io_data.openssl_io.ssl, SSL_MODE_AUTO_RETRY);

        	/* We might want to do other things with ssl here */


	
		char * host_str = malloc(20 * sizeof(char));
		snprintf(host_str, 20, "%s:%d", host, port);
        	BIO_set_conn_hostname(psocket_data->io_data.openssl_io.sbio, host_str);
		free(host_str);

        	if(BIO_do_connect(psocket_data->io_data.openssl_io.sbio) <= 0) {
//                		fprintf(stderr, "Error connecting to server\n");
//                		ERR_print_errors_fp(stderr);
			return -1;
        		}

        	if(BIO_do_handshake(psocket_data->io_data.openssl_io.sbio) <= 0) {
//                		fprintf(stderr, "Error establishing SSL connection\n");
//                		ERR_print_errors_fp(stderr);
			return -1;
       		 }
		psocket_data->io_data.openssl_io.bio = psocket_data->io_data.openssl_io.sbio;
	}
	#endif	

	return 0;
}

void portable_shutdown(struct st_psocket * psocket_data){
	portable_close_client(psocket_data);
	portable_close_server(psocket_data);
}

void portable_close_server(struct st_psocket * psocket_data){
	if(psocket_data->io_method == IO_BSD)
		closesocket(psocket_data->io_data.bsd_io.serverfd);

	/*SSL we only close the client, and a portable_free takes care of server stuff
         *Both need to be called anyway*/
}
void portable_close_client(struct st_psocket * psocket_data){
	if(psocket_data->io_method == IO_BSD)
		closesocket(psocket_data->io_data.bsd_io.clientfd);

	#ifdef USE_OPENSSL
	else if(psocket_data->io_method == IO_OPENSSL){
		if(psocket_data->io_data.openssl_io.sbio != NULL)
        		BIO_free_all(psocket_data->io_data.openssl_io.sbio); /*Accept/Client BIO*/
		psocket_data->io_data.openssl_io.sbio = NULL;
	}
	#endif	
}

/*
 *  FILE: 
 *  	portable_socket.h
 *
 *  DESCRIPTION:
 *  	Set of functions dealing with socket initialization, read/writes, or
 *      even socket creation on Win32.  You may choose use OpenSSL or BSD sockets.
 *
 *  FUNCTIONS:
 *      socketpair()  - Very simple rewrite of socketpair on Win32 for 
 *                      AF_LOCAL/SOCK_STREAM connection, with no options.
 *                      Call socket_init() if problems with binary data occur. 
 *      socket_init()  -SIGPIPE ignore for *n*x, and winsock/_fmode stuff on Windows.
 *                      Please Note: this function on windows changes all pipes to binary.
 *  	readline_r()  - Reentrant readline function with support for CRLF, 
 *                      or just CR.
 *  	fullsend()    - Write data without worrying about all of it being written.  
 *                      Useful for sockets.
 * 
 *
 * Copyright (c) 2004-2006 Karlan Thomas Mitchell<[EMAIL PROTECTED]>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, is prohibited except by
 * Karlan Thomas Mitchell.
 *
 * THIS SOFTWARE IS PROVIDED BY KARLAN THOMAS MITCHELL AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PORTABLE_SOCKET_H
#define _PORTABLE_SOCKET_H




#ifdef __WIN32__
       #ifdef __CYGWIN__
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <netinet/in.h>
          #include <arpa/inet.h>
       #else
         /*Any compiler except Cygwin*/
          #define socklen_t int
          #include <winsock.h>
       #endif
#else
     #include <fcntl.h>
     #include <sys/ioctl.h>
     #define closesocket close 
     #include <sys/types.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
#endif


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>


#ifdef USE_OPENSSL
       #include <openssl/bio.h>
       #include <openssl/ssl.h>
       #include <openssl/err.h>
#endif

#ifndef closesocket
	#define closesocket close
#endif




#ifndef AF_LOCAL
	#define AF_LOCAL AF_UNIX
#endif

#define IO_OPENSSL 0
#define IO_BSD     1






struct st_psocket_bsd {
	/*Native IO Method: IO_BSD*/
	int                         serverfd;
	struct sockaddr_in          serveraddr;
	int			    clientfd;
	struct sockaddr_in          clientaddr;
};

struct st_psocket_openssl {
	#ifdef USE_OPENSSL
	/*OpenSSL IO Method: IO_OPENSSL*/
	SSL_CTX * ctx; /*OpenSSL connection*/
	SSL     * ssl; /*Used for SSL communication*/
	BIO     * bio;  /*Used by Accept*/
	BIO     * sbio;	/*Used for SSL communication*/
	#endif
};


union st_psocket_union {
	struct st_psocket_bsd      bsd_io;
	struct st_psocket_openssl openssl_io;
};

struct  st_psocket {
	int io_method;
	union st_psocket_union io_data;
};


struct st_timeval {
         long    tv_sec;         /* seconds */
         };


int sock_nonblock(int sock);
#ifdef __WIN32__
#ifndef __CYGWIN__
int socketpair(int domain, int type, int protocol, int sv[2]);
#endif /*!CYGWIN*/
#endif /*Win32*/



int psocket_environment_init();
#ifdef USE_OPENSSL
ssize_t BIO_readline_r(BIO * bio, char * buffer, ssize_t bufferlen);
ssize_t BIO_fullsend(BIO *  bio, char * buffer, ssize_t buflen);
#endif
ssize_t readline_r(int fd, char * buffer, ssize_t bufferlen, int read_socket);
ssize_t readline_r_timeout(int fd, char * buffer, ssize_t bufferlen, int read_socket, struct st_timeval * time_data);
ssize_t fullsend(int socketd, char * buffer, ssize_t buflen);

ssize_t portable_setnonblock(struct st_psocket * portable_data);

ssize_t portable_read_timeout(struct st_psocket * portable_data, char * buffer, size_t bufferlen, struct st_timeval * time_data);
ssize_t portable_write_timeout(struct st_psocket * portable_data, char * buffer, size_t bufferlen, struct st_timeval * time_data);

ssize_t portable_read(struct st_psocket * portable_data, char * buffer, size_t bufferlen);
ssize_t portable_write(struct st_psocket * psocket_data, char * buffer, size_t bufferlen);
ssize_t portable_readline_r(struct st_psocket * psocket_data, char * buffer, ssize_t bufferlen);
ssize_t portable_fullsend(struct st_psocket * psocket_data, char * buffer, ssize_t bufferlen);
char * portable_get_client_ip(struct st_psocket * psocket_data);
#ifdef USE_OPENSSL
int portable_ssl_bind(struct st_psocket * psocket_data, char * address, int short unsigned port, char * pem);
#endif


int portable_bind(struct st_psocket * psocket_data, char * address, int short unsigned port);
int portable_set_openssl(struct st_psocket * psocket_data, char * pem);
int portable_copy(struct st_psocket * new_psocket, struct st_psocket * old_psocket);
int portable_accept(struct st_psocket * psocket_data);
int portable_connect(struct st_psocket * psocket_data, char * host, int unsigned short port);
void portable_shutdown(struct st_psocket * psocket_data);
void portable_close_server(struct st_psocket * psocket_data);
void portable_close_client(struct st_psocket * psocket_data);

#endif

Reply via email to