From 460d9286145ec5a4b471e1ede75fc62f074ddfe5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Fri, 17 Nov 2006 12:48:03 +0000 Subject: [PATCH] initial checkin of network communication [r8385] --- ir/net/Makefile.in | 33 ++++++++++++ ir/net/firmnet.c | 127 +++++++++++++++++++++++++++++++++++++++++++++ ir/net/firmnet.h | 76 +++++++++++++++++++++++++++ ir/net/firmnet_t.h | 46 ++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 ir/net/Makefile.in create mode 100644 ir/net/firmnet.c create mode 100644 ir/net/firmnet.h create mode 100644 ir/net/firmnet_t.h diff --git a/ir/net/Makefile.in b/ir/net/Makefile.in new file mode 100644 index 000000000..abc71cb72 --- /dev/null +++ b/ir/net/Makefile.in @@ -0,0 +1,33 @@ +# +# Project: libFIRM +# File name: ir/debug/Makefile.in +# Purpose: +# Author: Boris Boesler, Till Riedel +# Modified by: +# Created: +# CVS-ID: $Id$ +# Copyright: (c) 1999-2003 Universität Karlsruhe +# Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. +# + +top_srcdir := @top_srcdir@ +srcdir = @srcdir@ +topdir = ../.. +subdir := ir/net + +INSTALL_HEADERS = firmnet.h + +SOURCES = $(INSTALL_HEADERS) + +SOURCES += Makefile.in firmnet.c + +include $(topdir)/MakeRules + +CPPFLAGS += -I$(top_srcdir)/ir/ident -I$(top_srcdir)/ir/ir -I$(top_srcdir)/ir/tv \ + -I$(top_srcdir)/ir/tr -I$(top_srcdir)/ir/common -I$(top_srcdir)/ir/ana \ + -I$(top_srcdir)/ir/st -I$(top_srcdir)/ir/adt -I$(top_srcdir)/ir/external \ + -I$(topdir)/ir/config + +include $(top_srcdir)/MakeTargets + +all: subdir.o diff --git a/ir/net/firmnet.c b/ir/net/firmnet.c new file mode 100644 index 000000000..50af0b002 --- /dev/null +++ b/ir/net/firmnet.c @@ -0,0 +1,127 @@ +#include "firmnet_t.h" + +#ifdef _WIN32 +static int winsock_init(void) { + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + return 0; + } + + /* Confirm that the WinSock DLL supports 2.2.*/ + /* Note that if the DLL supports versions greater */ + /* than 2.2 in addition to 2.2, it will still return */ + /* 2.2 in wVersion since that is the version we */ + /* requested. */ + + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 2 ) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + WSACleanup( ); + return 0; + } + return 1; +} +#endif /* _WIN32 */ + +int firmnet_connect_tcp(const char *host, uint16_t port) +{ + struct hostent *phe; + struct protoent *ppe; + struct sockaddr_in sin; + int s; + +#ifdef _WIN32 + winsock_init(); +#endif + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + + if ((phe = gethostbyname(host))) + memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); + else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) { + fprintf(stderr, "cannot get host entry for %s", host); + return -1; + } + + ppe = getprotobyname("tcp"); + ERRNO_CHECK_RETURN(s = socket(PF_INET, SOCK_STREAM, ppe->p_proto), <, 0, -1); + ERRNO_CHECK_RETURN(connect(s, (struct sockaddr *) &sin, sizeof(sin)), <, 0, -1); + + return s; +} + +void firmnet_close_socket(int fd) { +#ifdef _WIN32 + closesocket(fd); +#else /* _WIN32 */ + close(fd); +#endif /* _WIN32 */ +} + +/** + * Send message of size @p n from buffer @p buf to file descriptor @p fd. + * @param fd The file descriptor, the message should be send to. + * @param buf The buffer containing the message + * @param n The length of the message. + * @return Number of bytes written or -1 on failure. + */ +ssize_t firmnet_send(int fd, const void *buf, size_t n) +{ + ssize_t res; + size_t bytes_written = 0; + const char *data = buf; + + do { + res = send(fd, &data[bytes_written], n - bytes_written, 0); + if (res < 0) { + if (errno != EAGAIN) + return -1; + continue; + } + + bytes_written += res; + + } while (bytes_written < n); + + return n; +} + +/** + * Try to read some bytes but block until a certain amount is read. + * @param fd The file descriptor. + * @param buf The buffer to read into. + * @param try The amount of bytes to try to read. + * @param at_least block until this many bytes are read. + * @return The number of bytes read or -1 on error. + */ +ssize_t firmnet_recv(int fd, void *buf, size_t try, size_t at_least) +{ + ssize_t res; + size_t bytes_read = 0; + char *data = buf; + + do { + res = recv(fd, &data[bytes_read], try - bytes_read, 0); + if (res <= 0) { + if (res == 0 || errno != EAGAIN) + return -1; + continue; + } + + bytes_read += res; + + } while (bytes_read < at_least); + + return bytes_read; +} diff --git a/ir/net/firmnet.h b/ir/net/firmnet.h new file mode 100644 index 000000000..5108709bd --- /dev/null +++ b/ir/net/firmnet.h @@ -0,0 +1,76 @@ +#ifndef _FIRMNET_H_ +#define _FIRMNET_H_ + +#ifdef _WIN32 +#include +#include + +#else /* _WIN32 */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#endif /* _WIN32 */ + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + +typedef size_t ssize_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; + +#else /* _MSC_VER */ + +#include +#include +#include +#include + +#endif /* _MSC_VER */ + +/** + * Establishes a TCP/IP connection to @p host at port @p port. + * @param host Hostname to connect to + * @param port Port number + * @return The file descriptor on success, -1 otherwise + */ +int firmnet_connect_tcp(const char *host, uint16_t port); + +/** + * Closes connection established on socket @p fd. + * @param fd The file descriptor identifying the connection + */ +void firmnet_close_socket(int fd); + +/** + * Send message of size @p n from buffer @p buf to file descriptor @p fd. + * @param fd The file descriptor, the message should be send to. + * @param buf The buffer containing the message + * @param n The length of the message. + * @return Number of bytes written or -1 on failure. + */ +ssize_t firmnet_send(int fd, const void *buf, size_t n); + +/** + * Try to read some bytes but block until a certain amount is read. + * @param fd The file descriptor. + * @param buf The buffer to read into. + * @param try The amount of bytes to try to read. + * @param at_least block until this many bytes are read. + * @return The number of bytes read or -1 on error. + */ +ssize_t firmnet_recv(int fd, void *buf, size_t try, size_t at_least); + +#endif /* _FIRMNET_H_ */ diff --git a/ir/net/firmnet_t.h b/ir/net/firmnet_t.h new file mode 100644 index 000000000..c0557f7e0 --- /dev/null +++ b/ir/net/firmnet_t.h @@ -0,0 +1,46 @@ +#ifndef _FIRMNET_T_H_ +#define _FIRMNET_T_H_ + +#include "firmnet.h" + +#define BASIC_ERR_CHECK(expr,op,cond,fmt,last) \ +{ \ + int res; \ + if((res = (expr)) op cond) { \ + fprintf(stderr, "%s(%d): %d = %s(%d): ", \ + __FILE__, __LINE__, res, #expr, cond); \ + lpp_print_err fmt; \ + fprintf(stderr, "\n"); \ + last; \ + } \ +} + +#define BASIC_ERRNO_CHECK(expr,op,cond,last) \ +{ \ + int _basic_errno_check_res = (expr); \ + if(_basic_errno_check_res op cond) { \ + fprintf(stderr, "%s(%d): %d = %s(%d): %s\n", \ + __FILE__, __LINE__, _basic_errno_check_res, #expr, cond, strerror(errno)); \ + last; \ + } \ +} + +#define ERR_CHECK_RETURN(expr, op, cond, fmt, retval) \ + BASIC_ERR_CHECK(expr, op, cond, fmt, return retval) + +#define ERRNO_CHECK_RETURN(expr, op, cond, retval) \ + BASIC_ERRNO_CHECK(expr, op, cond, return retval) + +#define ERR_CHECK_RETURN_VOID(expr, op, cond, fmt) \ + BASIC_ERR_CHECK(expr, op, cond, fmt, return) + +#define ERRNO_CHECK_RETURN_VOID(expr, op, cond) \ + BASIC_ERRNO_CHECK(expr, op, cond, return) + +#define ERR_CHECK(expr, op, cond, fmt) \ + BASIC_ERR_CHECK(expr, op, cond, fmt, (void) 0) + +#define ERRNO_CHECK(expr, op, cond) \ + BASIC_ERRNO_CHECK(expr, op, cond, (void) 0) + +#endif /* _FIRMNET_T_H_ */ -- 2.20.1