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