--- include/cr_net.h +++ include/cr_net.h @@ -14,6 +14,7 @@ #endif #include +#include #include "cr_protocol.h" @@ -26,6 +27,7 @@ typedef enum { CR_NO_CONNECTION, CR_TCPIP, + CR_UDPTCPIP, CR_FILE, CR_GM, CR_DROP_PACKETS @@ -50,6 +52,7 @@ void crNetInit( CRNetReceiveFunc recvFunc, CRNetCloseFunc closeFunc ); void *crNetAlloc( CRConnection *conn ); void crNetSend( CRConnection *conn, void **bufp, void *start, unsigned int len ); +void crNetBarf( CRConnection *conn, void **bufp, void *start, unsigned int len ); void crNetSendExact( CRConnection *conn, void *start, unsigned int len ); void crNetSingleRecv( CRConnection *conn, void *buf, unsigned int len ); unsigned int crNetGetMessage( CRConnection *conn, CRMessage **message ); @@ -82,6 +85,7 @@ CRMultiBuffer multi; unsigned int mtu; + unsigned int buffer_size; int broker; @@ -92,6 +96,7 @@ void *(*Alloc)( CRConnection *conn ); void (*Send)( CRConnection *conn, void **buf, void *start, unsigned int len ); + void (*Barf)( CRConnection *conn, void **buf, void *start, unsigned int len ); void (*SendExact)( CRConnection *conn, void *start, unsigned int len ); void (*Recv)( CRConnection *conn, void *buf, unsigned int len ); void (*Free)( CRConnection *conn, void *buf ); @@ -113,6 +118,15 @@ /* TCP/IP */ CRSocket tcp_socket; int index; + + /* UDP/IP */ + CRSocket udp_socket; + struct sockaddr_storage remoteaddr; + + /* UDP/TCP/IP */ + unsigned int seq; + void *udp_packet; + int udp_packetlen; /* FILE Tracing */ enum { CR_FILE_WRITE, CR_FILE_READ } file_direction; --- include/cr_pack.h +++ include/cr_pack.h @@ -29,9 +29,13 @@ typedef struct { void *pack; unsigned int size; + unsigned int mtu; unsigned char *data_start, *data_current, *data_end; unsigned char *opcode_start, *opcode_current, *opcode_end; GLboolean geometry_only; /* just used for debugging */ + GLboolean holds_BeginEnd; + GLboolean in_BeginEnd; + GLboolean canBarf; } CRPackBuffer; typedef void (*CRPackFlushFunc)(void *arg); @@ -56,8 +60,8 @@ void crPackSetBuffer( CRPackContext *pc, CRPackBuffer *buffer ); void crPackGetBuffer( CRPackContext *pc, CRPackBuffer *buffer ); -void crPackInitBuffer( CRPackBuffer *buffer, void *buf, int size, int extra ); -void crPackResetPointers( CRPackContext *pc, int extra ); +void crPackInitBuffer( CRPackBuffer *buffer, void *buf, int size, int mtu ); +void crPackResetPointers( CRPackContext *pc ); void crPackFlushFunc( CRPackContext *pc, CRPackFlushFunc ff ); void crPackFlushArg( CRPackContext *pc, void *flush_arg ); void crPackSendHugeFunc( CRPackContext *pc, CRPackSendHugeFunc shf ); @@ -68,6 +72,8 @@ void crPackAppendBuffer( CRPackBuffer *buffer ); void crPackAppendBoundedBuffer( CRPackBuffer *buffer, GLrecti *bounds ); +int crPackCanHoldOpcode( int num_opcode, int num_data ); +int crPackCanHoldBuffer( CRPackBuffer *buffer ); #if defined(LINUX) || defined(WINDOWS) #define CR_UNALIGNED_ACCESS_OKAY @@ -84,24 +90,31 @@ void SanityCheck(void); -#define GET_BUFFERED_POINTER( pc, len ) \ +#define GET_BUFFERED_POINTER_NO_BEGINEND_FLUSH( pc, len ) \ THREADASSERT( pc ); \ data_ptr = pc->buffer.data_current; \ - if (data_ptr + (len) > pc->buffer.data_end ) \ + if ( !crPackCanHoldOpcode( 1, (len) ) ) \ { \ pc->Flush( pc->flush_arg ); \ data_ptr = pc->buffer.data_current; \ - CRASSERT( data_ptr + (len) <= pc->buffer.data_end ); \ + CRASSERT(crPackCanHoldOpcode( 1, (len) ) ); \ } \ pc->buffer.data_current += (len) +#define GET_BUFFERED_POINTER( pc, len ) \ + if ( pc->buffer.holds_BeginEnd && ! pc->buffer.in_BeginEnd ) { \ + pc->Flush( pc->flush_arg ); \ + pc->buffer.holds_BeginEnd = 0; \ + } \ + GET_BUFFERED_POINTER_NO_BEGINEND_FLUSH( pc, len ) + #define GET_BUFFERED_COUNT_POINTER( pc, len ) \ data_ptr = pc->buffer.data_current; \ - if (data_ptr + (len) > pc->buffer.data_end ) \ + if ( !crPackCanHoldOpcode( 1, (len) ) ) \ { \ pc->Flush( pc->flush_arg ); \ data_ptr = pc->buffer.data_current; \ - CRASSERT( data_ptr + (len) <= pc->buffer.data_end ); \ + CRASSERT( crPackCanHoldOpcode( 1, (len) ) ); \ } \ pc->current.vtx_count++; \ pc->buffer.data_current += (len) --- include/cr_server.h +++ include/cr_server.h @@ -50,6 +50,7 @@ int useL2; int mtu; + int buffer_size; char protocol[1024]; unsigned int muralWidth, muralHeight; --- mothership/client/client.c +++ mothership/client/client.c @@ -19,8 +19,6 @@ CRConnection *crMothershipConnect( void ) { char *mother_server = NULL; - int mother_port = MOTHERPORT; - char mother_url[1024]; crNetInit( NULL, NULL ); @@ -31,9 +29,7 @@ mother_server = "localhost"; } - sprintf( mother_url, "%s:%d", mother_server, mother_port ); - - return crNetConnectToServer( mother_server, 10000, 8096, 0 ); + return crNetConnectToServer( mother_server, MOTHERPORT, 8096, 0 ); } void crMothershipDisconnect( CRConnection *conn ) --- mothership/server/mothership.py +++ mothership/server/mothership.py @@ -93,14 +93,18 @@ """AddServer(node, protocol='tcpip', port=7000) Tells a client node where to find its server.""" node.Conf( 'port', port ) - if protocol == 'tcpip': - self.__add_server( node, "%s://%s:%d" % (protocol,node.ipaddr,port) ) - elif protocol.startswith('file'): + #if protocol == 'tcpip': + # self.__add_server( node, "%s://%s:%d" % (protocol,node.ipaddr,port) ) + #elif ... + if protocol.startswith('file'): self.__add_server( node, "%s" % protocol ) # Don't tell the server "node" about this. return else: self.__add_server( node, "%s://%s:%d" % (protocol,node.host,port) ) + # use this for tcp/ip : send hostname rather than ip + # (waiting for getaddrinfo, for probing which one is + # available) node.AddClient( self, protocol ) class CRNode: @@ -119,7 +123,8 @@ self.host = host if (host == 'localhost'): self.host = socket.gethostname() - self.ipaddr = socket.gethostbyname(self.host) + #self.ipaddr = socket.gethostbyname(self.host) + # deleted (see above) # unqualify the hostname if it is already that way. # e.g., turn "foo.bar.baz" into "foo" @@ -375,38 +380,46 @@ This starts the mothership's event loop.""" print >> sys.stderr, "This is Chromium, Version ALPHA" try: - HOST = "" - try: - s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) - except: - Fatal( "Couldn't create socket" ); - - try: - s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) - except: - Fatal( "Couldn't set the SO_REUSEADDR option on the socket!" ) + for res in socket.getaddrinfo(None, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + af, socktype, proto, canonname, sa = res - try: - s.bind( (HOST, PORT) ) - except: - Fatal( "Couldn't bind to port %d" % PORT ); + try: + s = socket.socket( af, socktype ) + except: + CRDebug( "Couldn't create socket of family %u, trying another one" % af ); + continue + + try: + s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) + except: + CRDebug( "Couldn't set the SO_REUSEADDR option on the socket!" ) + continue + + try: + s.bind( sa ) + except: + CRDebug( "Couldn't bind to port %d" % PORT ); + continue + + try: + s.listen(100) + except: + CRDebug( "Couldn't listen!" ); + continue - try: - s.listen(100) - except: - Fatal( "Couldn't listen!" ); - - self.all_sockets.append(s) - - while 1: - ready = select.select( self.all_sockets, [], [], 0.1 )[0] - for sock in ready: - if sock == s: - conn, addr = s.accept() - self.wrappers[conn] = SockWrapper(conn) - self.all_sockets.append( conn ) - else: - self.ProcessRequest( self.wrappers[sock] ) + CRDebug( "Mothership ready" ); + self.all_sockets.append(s) + + while 1: + ready = select.select( self.all_sockets, [], [], 0.1 )[0] + for sock in ready: + if sock == s: + conn, addr = s.accept() + self.wrappers[conn] = SockWrapper(conn) + self.all_sockets.append( conn ) + else: + self.ProcessRequest( self.wrappers[sock] ) + Fatal( "Couldn't find local TCP port") except KeyboardInterrupt: try: for sock in self.all_sockets: @@ -446,9 +459,9 @@ Connects the given socket.""" connect_info = args.split( " " ) protocol = connect_info[0] - if (protocol == 'tcpip'): + if (protocol == 'tcpip' or protocol == 'udptcpip'): (p, hostname, port_str, endianness_str) = connect_info - hostname = socket.gethostbyname(hostname) + #hostname = socket.gethostbyname(hostname) port = int(port_str) endianness = int(endianness_str) for server_sock in self.wrappers.values(): @@ -460,7 +473,7 @@ self.conn_id += 1 return else: - CRDebug( "not connecting to \"%s\" (!= \"%s\")" % (server_hostname, hostname) ) + CRDebug( "not connecting to \"%s:%d\" (!= \"%s:%d\")" % (server_hostname, server_port, hostname, port) ) sock.tcpip_connect_wait = (hostname, port, endianness) elif (protocol == 'gm'): (p, hostname, port_str, node_id_str, port_num_str, endianness_str) = connect_info @@ -485,9 +498,9 @@ Accepts the given socket.""" accept_info = args.split( " " ) protocol = accept_info[0] - if protocol == 'tcpip': + if protocol == 'tcpip' or protocol == 'udptcpip': (p, hostname, port_str, endianness_str) = accept_info - hostname = socket.gethostbyname(hostname) + #hostname = socket.gethostbyname(hostname) port = int(port_str) endianness = int(endianness_str) for client_sock in self.wrappers.values(): @@ -499,7 +512,7 @@ self.conn_id += 1 return else: - CRDebug( "not accepting from \"%s\" (!= \"%s\")" % (client_hostname, hostname ) ) + CRDebug( "not accepting from \"%s:%d\" (!= \"%s:%d\")" % (client_hostname, client_port, hostname, port ) ) sock.tcpip_accept_wait = (hostname, port, endianness) elif protocol == 'gm': --- packer/Makefile +++ packer/Makefile @@ -10,6 +10,7 @@ NORMAL_FILES = packer \ pack_arrays \ pack_bbox \ + pack_beginend \ pack_bounds \ pack_buffer \ pack_client \ --- packer/pack_buffer.c +++ packer/pack_buffer.c @@ -61,18 +61,25 @@ pc->SendHuge = shf; } -void crPackResetPointers( CRPackContext *pc, int extra ) +void crPackResetPointers( CRPackContext *pc ) { const GLboolean g = pc->buffer.geometry_only; /* save this flag */ - crPackInitBuffer( &(pc->buffer), pc->buffer.pack, pc->buffer.size, extra ); + const GLboolean holds_BeginEnd = pc->buffer.holds_BeginEnd; + const GLboolean in_BeginEnd = pc->buffer.in_BeginEnd; + const GLboolean canBarf = pc->buffer.canBarf; + crPackInitBuffer( &(pc->buffer), pc->buffer.pack, pc->buffer.size, pc->buffer.mtu ); pc->buffer.geometry_only = g; /* restore the flag */ + pc->buffer.holds_BeginEnd = holds_BeginEnd; + pc->buffer.in_BeginEnd = in_BeginEnd; + pc->buffer.canBarf = canBarf; } -void crPackInitBuffer( CRPackBuffer *buf, void *pack, int size, int extra ) +void crPackInitBuffer( CRPackBuffer *buf, void *pack, int size, int mtu ) { unsigned int num_opcodes; buf->size = size; + buf->mtu = mtu; buf->pack = pack; /* Each opcode has at least a 1-word payload, so opcodes can occupy at most @@ -91,42 +98,81 @@ buf->opcode_current = buf->opcode_start; buf->opcode_end = buf->opcode_start - num_opcodes; - buf->data_end -= extra; /* caller may want extra space (sigh) */ - buf->geometry_only = GL_FALSE; + buf->holds_BeginEnd = 0; + buf->in_BeginEnd = 0; + buf->canBarf = 0; +} + +int crPackCanHoldOpcode( int num_opcode, int num_data ) +{ + GET_PACKER_CONTEXT(pc); + return (((pc->buffer.data_current - pc->buffer.opcode_current - 1 + + num_opcode + num_data + + 0x3 ) & ~0x3) + sizeof(CRMessageOpcodes) + <= pc->buffer.mtu + && pc->buffer.opcode_current - num_opcode >= pc->buffer.opcode_end + && pc->buffer.data_current + num_data <= pc->buffer.data_end ); +} + +int crPackCanHoldBuffer( CRPackBuffer *src ) +{ + int num_data = src->data_current - src->data_start; + int num_opcode = src->opcode_start - src->opcode_current; + return crPackCanHoldOpcode( num_opcode, num_data ); } void crPackAppendBuffer( CRPackBuffer *src ) { GET_PACKER_CONTEXT(pc); int num_data = src->data_current - src->data_start; - int num_opcode; + int num_opcode = src->opcode_start - src->opcode_current; + + if (!crPackCanHoldBuffer(src)) + { + if (src->holds_BeginEnd) + { + crWarning( "crPackAppendBuffer: overflowed the destination!" ); + return; + } + else + crError( "crPackAppendBuffer: overflowed the destination!" ); + } - if ( pc->buffer.data_current + num_data > pc->buffer.data_end ) - crError( "crPackAppendBuffer: overflowed the destination!" ); crMemcpy( pc->buffer.data_current, src->data_start, num_data ); pc->buffer.data_current += num_data; - num_opcode = src->opcode_start - src->opcode_current; CRASSERT( pc->buffer.opcode_current - num_opcode >= pc->buffer.opcode_end ); crMemcpy( pc->buffer.opcode_current + 1 - num_opcode, src->opcode_current + 1, num_opcode ); pc->buffer.opcode_current -= num_opcode; + pc->buffer.holds_BeginEnd |= src->holds_BeginEnd; + pc->buffer.in_BeginEnd = src->in_BeginEnd; } void crPackAppendBoundedBuffer( CRPackBuffer *src, GLrecti *bounds ) { GET_PACKER_CONTEXT(pc); - int length = src->data_current - ( src->opcode_current + 1 ); + int length = src->data_current - src->opcode_current - 1; + int len_aligned = (length + 3) & ~3; /* 24 is the size of the bounds-info packet... */ - if ( pc->buffer.data_current + length + 24 > pc->buffer.data_end ) - crError( "crPackAppendBoundedBuffer: overflowed the destination!" ); + if ( !crPackCanHoldOpcode( 1, len_aligned + 24 ) ) + { + if (src->holds_BeginEnd) { + crWarning( "crPackAppendBoundedBuffer: overflowed the destination!" ); + return; + } + else + crError( "crPackAppendBoundedBuffer: overflowed the destination!" ); + } crPackBoundsInfo( bounds, (GLbyte *) src->opcode_current + 1, length, src->opcode_start - src->opcode_current ); + pc->buffer.holds_BeginEnd |= src->holds_BeginEnd; + pc->buffer.in_BeginEnd = src->in_BeginEnd; } void *crPackAlloc( unsigned int size ) @@ -137,7 +183,7 @@ /* include space for the length and make the payload word-aligned */ size = ( size + sizeof(unsigned int) + 0x3 ) & ~0x3; - if ( pc->buffer.data_current + size <= pc->buffer.data_end ) + if ( crPackCanHoldOpcode( 1, size ) ) { /* we can just put it in the current buffer */ GET_BUFFERED_POINTER(pc, size ); @@ -146,7 +192,7 @@ { /* Okay, it didn't fit. Maybe it will after we flush. */ pc->Flush( pc->flush_arg ); - if ( pc->buffer.data_current + size <= pc->buffer.data_end ) + if ( crPackCanHoldOpcode( 1, size ) ) { GET_BUFFERED_POINTER(pc, size ); } --- packer/packer.py +++ packer/packer.py @@ -128,15 +128,6 @@ print "\tpc->current.%s.%s = data_ptr;" % (name,type) return - m = re.match( r"^(Begin)$", func_name ) - if m : - k = m.group(1) - name = '%s%s' % (k[:1].lower(),k[1:]) - type = "" - print "\tpc->current.%s_data = data_ptr;" % name - print "\tpc->current.%s_op = pc->buffer.opcode_current;" % name - return - for func_name in keys: ( return_type, arg_names, arg_types ) = gl_mapping[func_name] if stub_common.FindSpecial( "packer", func_name ): continue @@ -193,11 +184,14 @@ print "\tCRASSERT(!pc->buffer.geometry_only); /* sanity check */" if packet_length == 0: print "\tGET_BUFFERED_POINTER_NO_ARGS( pc );" + elif func_name[:9] == "Translate" or func_name[:5] == "Color": + if is_extended: + packet_length += 8 + print "\tGET_BUFFERED_POINTER_NO_BEGINEND_FLUSH( pc, %d );" % packet_length else: if is_extended: packet_length += 8 print "\tGET_BUFFERED_POINTER( pc, %d );" % packet_length - UpdateCurrentPointer( func_name ) counter = 0 --- packer/packer_special +++ packer/packer_special @@ -73,3 +73,5 @@ CombinerStageParameterfvNV ChromiumParametervCR crCreateWindow +Begin +End --- progs/packperf/packperf.c +++ progs/packperf/packperf.c @@ -16,7 +16,7 @@ void reset_buffer( void *arg ) { - crPackResetPointers( pack_context, 0 ); + crPackResetPointers( pack_context ); UNUSED(arg); } @@ -53,7 +53,7 @@ CRPackBuffer pack_buffer; pack_context = crPackNewContext( 0 ); /* Don't swap bytes, for God's sake */ crPackSetContext( pack_context ); - crPackInitBuffer( &pack_buffer, crAlloc( 1024*1024 ), 1024*1024, 0 ); + crPackInitBuffer( &pack_buffer, crAlloc( 1024*1024 ), 1024*1024, 1024*1024 ); crPackSetBuffer( pack_context, &pack_buffer ); crPackFlushFunc( pack_context, reset_buffer ); --- spu/binaryswap/binaryswapspu.c +++ spu/binaryswap/binaryswapspu.c @@ -347,11 +347,15 @@ crNetGetMessage( binaryswap_spu.peer_recv[i], &incoming_msg); crNetSend( binaryswap_spu.peer_send[i], NULL, binaryswap_spu.outgoing_msg, (width[i]*height[i]*4) + binaryswap_spu.offset); + if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu) + binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu; } /* higher of pair => send,recv */ else{ crNetSend( binaryswap_spu.peer_send[i], NULL, binaryswap_spu.outgoing_msg, (width[i]*height[i]*4) + binaryswap_spu.offset); + if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu) + binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu; crNetGetMessage( binaryswap_spu.peer_recv[i], &incoming_msg); } @@ -404,12 +408,16 @@ crNetGetMessage( binaryswap_spu.peer_recv[i], &incoming_msg); crNetSend( binaryswap_spu.peer_send[i], NULL, binaryswap_spu.outgoing_msg, width[i]*height[i]*(3+4) + binaryswap_spu.offset); + if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu) + binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu; } /* higher of pair => send,recv */ else{ crNetSend( binaryswap_spu.peer_send[i], NULL, binaryswap_spu.outgoing_msg, width[i]*height[i]*(3+4) + binaryswap_spu.offset); + if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu) + binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu; crNetGetMessage( binaryswap_spu.peer_recv[i], &incoming_msg); } --- spu/comm/commspu.c +++ spu/comm/commspu.c @@ -23,6 +23,8 @@ comm_spu.msg->header.type = CR_MESSAGE_OOB; comm_spu.msg->frame_counter = frame_counter; crNetSend( comm_spu.peer_send, NULL, comm_spu.msg, comm_spu.num_bytes ); + if (comm_spu.mtu > comm_spu.peer_send->mtu) + comm_spu.mtu = comm_spu.peer_send->mtu; crNetGetMessage( comm_spu.peer_recv, &incoming_msg ); ping = (CommSPUPing *) incoming_msg; --- spu/hiddenline/hiddenlinespu_buffer.c +++ spu/hiddenline/hiddenlinespu_buffer.c @@ -19,7 +19,7 @@ { buf = crAlloc( hiddenline_spu.buffer_size ); } - crPackInitBuffer( &(hiddenline_spu.pack_buffer), buf, hiddenline_spu.buffer_size, 0 ); + crPackInitBuffer( &(hiddenline_spu.pack_buffer), buf, hiddenline_spu.buffer_size, hiddenline_spu.buffer_size ); crPackSetBuffer( hiddenline_spu.packer, &(hiddenline_spu.pack_buffer) ); } --- spu/pack/Makefile +++ spu/pack/Makefile @@ -8,6 +8,7 @@ SHARED = 1 LIBRARY = packspu FILES = packspu \ + packspu_beginend \ packspu_client \ packspu_config \ packspu_context \ @@ -43,3 +44,7 @@ packspu_pixel.c: packspu_pixel.py packspu_pixel_special @$(ECHO) Building the Pack SPU Pixel functions @$(PYTHON) packspu_pixel.py > $@ + +packspu_beginend.c: packspu_beginend.py packspu_vertex_special + @$(ECHO) Building the Pack SPU Vertex functions + @$(PYTHON) packspu_beginend.py > $@ --- spu/pack/pack.py +++ spu/pack/pack.py @@ -50,6 +50,7 @@ stub_common.FindSpecial( "packspu_pixel", func_name ) or stub_common.FindSpecial( "packspu_flush", func_name ) or stub_common.FindSpecial( "packspu_client", func_name ) or + stub_common.FindSpecial( "packspu_vertex", func_name ) or stub_common.FindSpecial( "../../packer/packer_get", func_name )): pack_specials.append( func_name ) --- spu/pack/packspu.h +++ spu/pack/packspu.h @@ -28,6 +28,10 @@ unsigned long id; CRNetServer server; CRPackBuffer buffer; + CRPackBuffer normBuffer; + CRPackBuffer BeginEndBuffer; + GLenum BeginEndMode; + int BeginEndState; ContextInfo *currentContext; CRPackContext *packer; }; --- /dev/null Sun Jul 7 21:43:18 2002 +++ spu/pack/packspu_beginend.py Mon Jul 8 14:08:04 2002 @@ -0,0 +1,150 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import sys,os; +import cPickle; +import string; +import re; + +sys.path.append( "../../opengl_stub" ) +parsed_file = open( "../../glapi_parser/gl_header.parsed", "rb" ) +gl_mapping = cPickle.load( parsed_file ) + +import stub_common; + +keys = gl_mapping.keys() +keys.sort(); + +stub_common.CopyrightC() + +print """/* DO NOT EDIT - AUTOMATICALLY GENERATED BY packspu_beginend.py */ +#include "packspu.h" +#include "assert.h" +#include "cr_packfunctions.h" + +void PACKSPU_APIENTRY packspu_Begin( GLenum mode ) +{ + GET_THREAD(thread); + CRPackBuffer *buf = &thread->BeginEndBuffer; + + CRASSERT( mode >= GL_POINTS && mode <= GL_POLYGON ); + + if (pack_spu.swap) + { + crPackBeginSWAP( mode ); + } + else + { + crPackBegin( mode ); + } + + if ( thread->server.conn->Barf ) { + thread->BeginEndMode = mode; + thread->BeginEndState = -1; + if ( mode == GL_LINES || mode == GL_TRIANGLES || mode == GL_QUADS || mode == GL_POLYGON ) + { + CRASSERT(!buf->pack); + crPackGetBuffer( thread->packer, &thread->normBuffer ); + buf->pack = crNetAlloc( thread->server.conn ); + crPackInitBuffer( buf, buf->pack, thread->server.conn->buffer_size, thread->server.conn->mtu ); + crPackSetBuffer( thread->packer, buf ); + + thread->BeginEndState = 0; + } + } +} + +void PACKSPU_APIENTRY packspu_End( void ) +{ + GET_THREAD(thread); + CRPackBuffer *buf = &thread->BeginEndBuffer; + + if ( thread->server.conn->Barf && + (thread->BeginEndMode == GL_LINES + || thread->BeginEndMode == GL_TRIANGLES + || thread->BeginEndMode == GL_QUADS + || thread->BeginEndMode == GL_POLYGON ) ) + { + CRASSERT(buf->pack); + + crPackGetBuffer( thread->packer, buf ); + crPackSetBuffer( thread->packer, &thread->normBuffer ); + if ( !crPackCanHoldBuffer( buf ) ) + packspuFlush( (void *) thread ); + + crPackAppendBuffer( buf ); + crNetFree( thread->server.conn, buf->pack ); + buf->pack = NULL; + } + + if (pack_spu.swap) + { + crPackEndSWAP(); + } + else + { + crPackEnd(); + } +} + +static void DoVertex( void ) +{ + GET_THREAD(thread); + CRPackBuffer *buf = &thread->BeginEndBuffer; + CRPackBuffer *gbuf = &thread->normBuffer; + int num_data; + int num_opcode; + + //crDebug( "really doing Vertex" ); + crPackGetBuffer( thread->packer, buf ); + num_data = buf->data_current - buf->data_start; + num_opcode = buf->opcode_start - buf->opcode_current; + crPackSetBuffer( thread->packer, gbuf ); + if ( !crPackCanHoldBuffer( buf ) ) + // doesn't hold, first flush gbuf + packspuFlush( (void *) thread ); + + crPackAppendBuffer( buf ); + crPackGetBuffer( thread->packer, gbuf ); + crPackSetBuffer( thread->packer, buf ); + crPackResetPointers(thread->packer); +} + +static void RunState( void ) +{ + GET_THREAD(thread); + if (! thread->server.conn->Barf ) return; + if (thread->BeginEndState == -1) return; + switch(thread->BeginEndMode) { + case GL_POLYGON: + return; + case GL_LINES: + if ((thread->BeginEndState=(thread->BeginEndState+1)%2)) return; + break; + case GL_TRIANGLES: + if ((thread->BeginEndState=(thread->BeginEndState+1)%3)) return; + break; + case GL_QUADS: + if ((thread->BeginEndState=(thread->BeginEndState+1)%4)) return; + break; + } + DoVertex(); +} +""" + +for func_name in stub_common.AllSpecials( "packspu_vertex" ): + (return_type, args, types) = gl_mapping[func_name] + print 'void PACKSPU_APIENTRY packspu_%s%s' % ( func_name, stub_common.ArgumentString( args, types ) ) + print '{' + print '\tif (pack_spu.swap)' + print '\t{' + print '\t\tcrPack%sSWAP%s;' % ( func_name, stub_common.CallString( args ) ) + print '\t}' + print '\telse' + print '\t{' + print '\t\tcrPack%s%s;' % ( func_name, stub_common.CallString( args ) ) + print '\t}' + print '\tRunState();' + print '}' --- spu/pack/packspu_config.c +++ spu/pack/packspu_config.c @@ -54,6 +54,10 @@ crMothershipGetMTU( conn, response ); sscanf( response, "%d", &(pack_spu.buffer_size) ); + /* get a buffer which can hold one big big opcode (counter computing + * against packer/pack_buffer.c) */ + pack_spu.buffer_size = ((((pack_spu.buffer_size - sizeof(CRMessageOpcodes)) * 5 + 3) / 4 + 0x03) & ~0x03) + sizeof(CRMessageOpcodes); + crSPUPropogateGLLimits( conn, pack_spu.id, child_spu, &pack_spu.limits ); crMothershipDisconnect( conn ); --- spu/pack/packspu_context.c +++ spu/pack/packspu_context.c @@ -54,7 +54,8 @@ CRASSERT(thread->packer == NULL); thread->packer = crPackNewContext( pack_spu.swap ); crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->server.conn), - thread->server.buffer_size, 0 ); + thread->server.conn->buffer_size, thread->server.conn->mtu ); + thread->buffer.canBarf = thread->server.conn->Barf?GL_TRUE:GL_FALSE; crPackSetBuffer( thread->packer, &thread->buffer ); crPackFlushFunc( thread->packer, packspuFlush ); crPackFlushArg( thread->packer, (void *) thread ); --- spu/pack/packspu_net.c +++ spu/pack/packspu_net.c @@ -167,7 +167,7 @@ */ /* XXX these calls seem to help, but might be appropriate */ crPackSetBuffer( thread->packer, buf ); - crPackResetPointers(thread->packer, 0); + crPackResetPointers(thread->packer); return; } @@ -175,12 +175,19 @@ CRASSERT( thread->server.conn ); - crNetSend( thread->server.conn, &(buf->pack), hdr, len ); + if ( buf->holds_BeginEnd ) + crNetBarf( thread->server.conn, &(buf->pack), hdr, len ); + else + crNetSend( thread->server.conn, &(buf->pack), hdr, len ); buf->pack = crNetAlloc( thread->server.conn ); + if ( buf->mtu > thread->server.conn->mtu ) + buf->mtu = thread->server.conn->mtu; + crPackSetBuffer( thread->packer, buf ); - crPackResetPointers(thread->packer, 0); /* don't need extra room like tilesort */ + + crPackResetPointers(thread->packer); (void) arg; } --- spu/pack/packspu_special +++ spu/pack/packspu_special @@ -28,3 +28,5 @@ CreateContext MakeCurrent DestroyContext +Begin +End --- /dev/null +++ spu/pack/packspu_vertex_special @@ -0,0 +1,28 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +Vertex2d +Vertex2dv +Vertex2f +Vertex2fv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex3d +Vertex3dv +Vertex3f +Vertex3fv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex4d +Vertex4dv +Vertex4f +Vertex4fv +Vertex4i +Vertex4iv +Vertex4s +Vertex4sv --- spu/print/print.py +++ spu/print/print.py @@ -113,11 +113,19 @@ print '%s )\\n"%s );' % ( printfstr, argstr ) print '\tfflush( print_spu.fp );' - if return_type != "void": - print '\treturn', + if return_type == "GLint": + print '\t{' + print '\t\tint res =', else: - print '\t', + if return_type != "void": + print '\treturn', + else: + print '\t', print 'print_spu.passthrough.%s%s;' % ( func_name, stub_common.CallString( names ) ) + if return_type == "GLint": + print '\t\tfprintf( print_spu.fp, "= %d\\n", res);' + print '\t\treturn res;' + print '\t}' print '}' print 'SPUNamedFunctionTable print_table[] = {' --- spu/print/printspu_enums.c +++ spu/print/printspu_enums.c @@ -14,7 +14,7 @@ } GLT_enum_tab_ent; static GLT_enum_tab_ent __enum_tab_ents[256] = { - {0, 2},{2, 5},{7, 8},{15, 9},{24, 13},{37, 6},{43, 5},{48, 8},{56, 2}, + {1442, 10},{2, 5},{7, 8},{15, 9},{24, 13},{37, 6},{43, 5},{48, 8},{56, 2}, {58, 2},{60, 3},{63, 243},{306, 246},{552, 245},{-1, -1},{-1, -1}, {797, 6},{803, 3},{806, 10},{816, 2},{818, 11},{829, 16},{845, 4}, {849, 3},{852, 3},{855, 11},{866, 1},{867, 3},{870, 3},{873, 2},{875, 4}, @@ -1494,6 +1494,16 @@ "GL_OBJECT_POINT_SGIS", /* 0x81f5 */ "GL_EYE_LINE_SGIS", /* 0x81f6 */ "GL_OBJECT_LINE_SGIS", /* 0x81f7 */ + "GL_POINTS", /* 0x0000 */ + "GL_LINES", /* 0x0001 */ + "GL_LINE_LOOP", /* 0x0002 */ + "GL_LINE_STRIP", /* 0x0003 */ + "GL_TRIANGLES", /* 0x0004 */ + "GL_TRIANGLE_STRIP", /* 0x0005 */ + "GL_TRIANGLE_FAN", /* 0x0006 */ + "GL_QUADS", /* 0x0007 */ + "GL_QUAD_STRIP", /* 0x0008 */ + "GL_POLYGON", /* 0x0009 */ }; char * printspuEnumToStr(GLenum value) --- spu/tilesort/tilesortspu.h +++ spu/tilesort/tilesortspu.h @@ -109,6 +109,7 @@ float widthScale, heightScale; /* muralSize / windowSize */ unsigned int MTU; + unsigned int buffer_size; int num_servers; TileSortSPUServer *servers; --- spu/tilesort/tilesortspu_config.c +++ spu/tilesort/tilesortspu_config.c @@ -78,6 +78,10 @@ crDebug( "Got the MTU as %d", tilesort_spu.MTU ); + /* get a buffer which can hold one big big opcode (counter computing + * against packer/pack_buffer.c) */ + tilesort_spu.buffer_size = ((((tilesort_spu.MTU - sizeof(CRMessageOpcodes) ) * 5 + 3) / 4 + 0x3) & ~0x3) + sizeof(CRMessageOpcodes); + if (crMothershipGetSPUParam( conn, response, "split_begin_end") ) { sscanf( response, "%d", &(tilesort_spu.splitBeginEnd) ); @@ -164,7 +168,7 @@ crDebug( "Server %d: %s", i+1, server_url ); thread0->net[i].name = crStrdup( server_url ); - thread0->net[i].buffer_size = tilesort_spu.MTU; + thread0->net[i].buffer_size = tilesort_spu.buffer_size; if (!crMothershipGetTiles( conn, response, i )) { --- spu/tilesort/tilesortspu_context.c +++ spu/tilesort/tilesortspu_context.c @@ -20,17 +20,7 @@ { int i; - /* We need to mess with the pack size of the geometry buffer, since we - * may be using BoundsInfo packes, etc, etc. This is yucky. */ - thread->geom_pack_size = tilesort_spu.MTU; - thread->geom_pack_size -= sizeof( CRMessageOpcodes ); - thread->geom_pack_size -= 4; - - /* We need to shrink everything to fit in the DATA part of the server's send - * buffer since we're going to always send geometry as a BOUNDS_INFO - * packet. */ - thread->geom_pack_size = (thread->geom_pack_size * 4) / 5; - thread->geom_pack_size -= (24 + 1); /* 24 is the size of the BoundsInfo packet */ + thread->geom_pack_size = tilesort_spu.buffer_size; thread->pinchState.numRestore = 0; thread->pinchState.wind = 0; @@ -43,7 +33,11 @@ crPackSetContext( thread->packer ); /* sets the packer's per-thread context */ crPackInitBuffer( &(thread->geometry_pack), crAlloc( thread->geom_pack_size ), - thread->geom_pack_size, END_FLUFF ); + thread->geom_pack_size, tilesort_spu.MTU-(24+END_FLUFF+4+4)); + /* 24 is the size of the bounds info packet */ + /* END_FLUFF is the size of data of End */ + /* 4 since BoundsInfo opcode may take a whole 4 bytes */ + /* and 4 to let room for extra End's opcode, if needed */ thread->geometry_pack.geometry_only = GL_TRUE; crPackSetBuffer( thread->packer, &(thread->geometry_pack) ); crPackFlushFunc( thread->packer, tilesortspuFlush_callback ); @@ -55,8 +49,16 @@ CRASSERT(tilesort_spu.num_servers > 0); for (i = 0; i < tilesort_spu.num_servers; i++) + { crPackInitBuffer( &(thread->pack[i]), crNetAlloc( thread->net[i].conn ), - thread->net[i].buffer_size, 0 ); + thread->net[i].conn->buffer_size, thread->net[i].conn->mtu ); + if (thread->net[i].conn->Barf) + { + thread->pack[i].canBarf = GL_TRUE; + thread->packer->buffer.canBarf = GL_TRUE; + thread->geometry_pack.canBarf = GL_TRUE; + } + } thread->currentContext = NULL; @@ -86,9 +88,11 @@ for (i = 0; i < tilesort_spu.num_servers; i++) { thread->net[i].name = crStrdup( tilesort_spu.thread[0].net[i].name ); - thread->net[i].buffer_size = tilesort_spu.MTU; + thread->net[i].buffer_size = tilesort_spu.thread[0].net[i].buffer_size; /* Establish new connection to server[i] */ crNetNewClient( tilesort_spu.thread[0].net[i].conn, &(thread->net[i])); + if (tilesort_spu.MTU > thread->net[i].conn->mtu) + tilesort_spu.MTU = thread->net[i].conn->mtu; } tilesortspuInitThreadPacking( thread ); --- spu/tilesort/tilesortspu_flush.c +++ spu/tilesort/tilesortspu_flush.c @@ -74,24 +74,30 @@ hdr = __applySendBufferHeader( pack, &len ); - crNetSend( net->conn, &pack->pack, hdr, len ); - crPackInitBuffer( pack, crNetAlloc( net->conn ), pack->size, END_FLUFF ); + if ( pack->holds_BeginEnd ) + crNetBarf( net->conn, &pack->pack, hdr, len ); + else + crNetSend( net->conn, &pack->pack, hdr, len ); + + crPackInitBuffer( pack, crNetAlloc( net->conn ), net->conn->buffer_size, net->conn->mtu ); + pack->canBarf = net->conn->Barf ? GL_TRUE : GL_FALSE; } static void __appendBuffer( CRPackBuffer *src ) { GET_THREAD(thread); - int num_data = src->data_current - src->data_start; /*crWarning( "In __appendBuffer: %d bytes left, packing %d bytes", thread->packer->buffer.data_end - thread->packer->buffer.data_current, num_data ); */ - if ( thread->packer->buffer.data_current + num_data > thread->packer->buffer.data_end ) + if ( !crPackCanHoldBuffer(src) + || thread->packer->buffer.holds_BeginEnd ^ src->holds_BeginEnd) { /* No room to append -- send now */ /*crWarning( "OUT OF ROOM!") ; */ tilesortspuSendServerBuffer( thread->state_server_index ); crPackSetBuffer( thread->packer, &(thread->pack[thread->state_server_index]) ); + CRASSERT(crPackCanHoldBuffer( src )); } crPackAppendBuffer( src ); @@ -101,21 +107,23 @@ void __appendBoundedBuffer( CRPackBuffer *src, GLrecti *bounds ) { GET_THREAD(thread); - /* 24 is the size of the bounds info packet */ - int num_data = src->data_current - src->opcode_current - 1 + 24; + int length = ((src->data_current - src->opcode_current - 1) + 3) & ~3; - if (num_data == 24) + if (length == 0) { /* nothing to send. */ return; } - if ( thread->packer->buffer.data_current + num_data > thread->packer->buffer.data_end ) + /* 24 is the size of the bounds info packet */ + if ( !crPackCanHoldOpcode( 1, length + 24 ) + || thread->packer->buffer.holds_BeginEnd ^ src->holds_BeginEnd) { /* No room to append -- send now */ tilesortspuSendServerBuffer( thread->state_server_index ); crPackSetBuffer( thread->packer, &(thread->pack[thread->state_server_index]) ); + CRASSERT(crPackCanHoldOpcode( 1, length + 24 )); } crPackAppendBoundedBuffer( src, bounds ); @@ -355,7 +363,7 @@ /* First, test to see if this is a big packet. */ - if (thread->packer->buffer.size > thread->net[0].conn->mtu ) + if (thread->packer->buffer.size > tilesort_spu.buffer_size ) { crDebug( "It was a big packet!" ); big_packet_hdr = __applySendBufferHeader( &(thread->packer->buffer), &big_packet_len ); @@ -419,7 +427,7 @@ if ( thread->currentContext->State->current.inBeginEnd ) { /*crDebug( "Closing this Begin/end!!!" ); */ - thread->packer->buffer.data_end += END_FLUFF; + thread->packer->buffer.mtu += END_FLUFF + 4; /* 4 for opcode */ if (tilesort_spu.swap) { crPackEndSWAP(); @@ -525,20 +533,31 @@ thread->state_server = NULL; thread->state_server_index = -1; + for ( i = 0 ; i < tilesort_spu.num_servers; i++ ) + { + if (thread->pack[i].mtu > thread->net[i].conn->mtu) + thread->pack[i].mtu = thread->net[i].conn->mtu; + if (tilesort_spu.MTU > thread->net[i].conn->mtu) + tilesort_spu.MTU = thread->net[i].conn->mtu; + } if ( big_packet_hdr != NULL ) { /* Throw away the big packet and make a new, smaller one */ crDebug( "Throwing away the big packet" ); crFree( thread->geometry_pack.pack ); - crPackInitBuffer( &(thread->geometry_pack), crAlloc( thread->geom_pack_size ), - thread->geom_pack_size, END_FLUFF ); + crPackInitBuffer( &(thread->geometry_pack), crAlloc( thread->geom_pack_size ), + thread->geom_pack_size, tilesort_spu.MTU - (24+END_FLUFF+8) ); + + /* 24 is the size of the bounds info packet */ + /* and 8 since End and BoundInfo opcodes may indeed take this space */ } else { /*crDebug( "Reverting to the old geometry buffer" ); */ + thread->geometry_pack.mtu = tilesort_spu.MTU - (24+END_FLUFF+8); crPackSetBuffer( thread->packer, &(thread->geometry_pack ) ); - crPackResetPointers( thread->packer, END_FLUFF ); + crPackResetPointers( thread->packer ); } /*crDebug( "Resetting the current vertex count and friends" ); */ @@ -611,7 +630,7 @@ crPackInitBuffer( &(thread->geometry_pack), crAlloc( thread->geometry_pack.size << 1 ), - thread->geometry_pack.size << 1, END_FLUFF ); + thread->geometry_pack.size << 1, (thread->geometry_pack.size << 1) - (24+END_FLUFF+8) ); thread->geometry_pack.geometry_only = GL_TRUE; crPackSetBuffer( thread->packer, &(thread->geometry_pack) ); --- spu/tilesort/tilesortspu_init.c +++ spu/tilesort/tilesortspu_init.c @@ -50,6 +50,13 @@ tilesortspuGatherConfiguration( child ); tilesortspuConnectToServers(); /* set up thread0's server connection */ + if (tilesort_spu.MTU > thread0->net[0].conn->mtu) { + tilesort_spu.MTU = thread0->net[0].conn->mtu; + + /* get a buffer which can hold one big big opcode (counter computing + * against packer/pack_buffer.c) */ + tilesort_spu.buffer_size = ((((tilesort_spu.MTU - sizeof(CRMessageOpcodes) ) * 5 + 3) / 4 + 0x3) & ~0x3) + sizeof(CRMessageOpcodes); + } tilesort_spu.swap = thread0->net[0].conn->swap; tilesortspuInitThreadPacking( thread0 ); --- spu/tilesort/tilesortspu_net.c +++ spu/tilesort/tilesortspu_net.c @@ -104,6 +104,7 @@ } if (!crStrcmp( protocol, "tcpip" ) || + !crStrcmp( protocol, "udptcpip" ) || !crStrcmp( protocol, "gm" ) ) { some_net_traffic = 1; --- spu/tilesort/tilesortspu_pinch.c +++ spu/tilesort/tilesortspu_pinch.c @@ -28,7 +28,8 @@ CRASSERT(op <= thread->packer->buffer.opcode_start); \ CRASSERT(op > thread->packer->buffer.opcode_end); \ CRASSERT(data >= thread->packer->buffer.data_start); \ - CRASSERT(data < thread->packer->buffer.data_end) + CRASSERT(data < thread->packer->buffer.data_end); \ + CRASSERT(((data - op + 0x3) & ~0x3) + sizeof(CRMessageOpcodes) <= thread->packer->buffer.mtu) static const GLvectorf vdefault = {0.0f, 0.0f, 0.0f, 1.0f}; --- spu/tilesort/tilesortspu_pixels.c +++ spu/tilesort/tilesortspu_pixels.c @@ -42,11 +42,11 @@ return; } - if (crImageSize(format, type, width, height) > thread->net[0].conn->mtu ) { + if (crImageSize(format, type, width, height) > tilesort_spu.MTU ) { crError("DrawPixels called with insufficient MTU size\n" "Needed %d, but currently MTU is set at %d\n", crImageSize(format, type, width, height), - thread->net[0].conn->mtu ); + tilesort_spu.MTU ); return; } @@ -281,11 +281,11 @@ /* Munge the per server packing structures */ data_ptr = pack->data_current; - if (data_ptr + len > pack->data_end ) + if (!crPackCanHoldOpcode( 1, len ) ) { tilesortspuFlush( thread ); data_ptr = pack->data_current; - CRASSERT( data_ptr + len <= pack->data_end ); + CRASSERT( crPackCanHoldOpcode( 1, len ) ); } pack->data_current += len; WRITE_DATA( 0, GLint, new_x ); --- util/Makefile +++ util/Makefile @@ -31,6 +31,7 @@ string \ threads \ tcpip \ + udptcpip \ timer \ url PRECOMP = debug_opcodes.c --- util/devnull.c +++ util/devnull.c @@ -17,7 +17,7 @@ void *crDevnullAlloc( CRConnection *conn ) { - return crAlloc( conn->mtu ); + return crAlloc( conn->buffer_size ); } void crDevnullSingleRecv( CRConnection *conn, void *buf, unsigned int len ) --- util/filenet.c +++ util/filenet.c @@ -109,13 +109,13 @@ if ( buf == NULL ) { crDebug( "Buffer pool was empty, so I allocated %d bytes", - (int)(sizeof(CRFileBuffer) + conn->mtu) ); + (int)(sizeof(CRFileBuffer) + conn->buffer_size) ); buf = (CRFileBuffer *) - crAlloc( sizeof(CRFileBuffer) + conn->mtu ); + crAlloc( sizeof(CRFileBuffer) + conn->buffer_size ); buf->magic = CR_FILE_BUFFER_MAGIC; buf->kind = CRFileMemory; buf->pad = 0; - buf->allocated = conn->mtu; + buf->allocated = conn->buffer_size; } #ifdef CHROMIUM_THREADSAFE @@ -221,7 +221,7 @@ CRASSERT( len > 0 ); - if ( len <= conn->mtu ) + if ( len <= conn->buffer_size ) { file_buffer = (CRFileBuffer *) crFileAlloc( conn ) - 1; } --- util/gm.c +++ util/gm.c @@ -710,7 +710,7 @@ #endif if ( temp == NULL ) { - temp = (CRGmBuffer*)crAlloc( sizeof(CRGmBuffer) + gm_conn->conn->mtu ); + temp = (CRGmBuffer*)crAlloc( sizeof(CRGmBuffer) + gm_conn->conn->buffer_size ); temp->magic = CR_GM_BUFFER_RECV_MAGIC; temp->kind = CRGmMemoryUnpinned; temp->pad = 0; @@ -1000,7 +1000,7 @@ unsigned char *src; CRASSERT( buf != NULL && len > 0 ); - if ( len <= conn->mtu ) + if ( len <= conn->buffer_size ) { /* the user is doing a send from memory not allocated by the * network layer, but it does fit within a single message, so @@ -1027,11 +1027,11 @@ CRMessageMulti *msg = (CRMessageMulti *) crGmAlloc( conn ); unsigned int n_bytes; - if ( len + sizeof(*msg) > conn->mtu ) + if ( len + sizeof(*msg) > conn->buffer_size ) { msg->header.type = CR_MESSAGE_MULTI_BODY; msg->header.conn_id = conn->id; - n_bytes = conn->mtu - sizeof(*msg); + n_bytes = conn->buffer_size - sizeof(*msg); } else { --- util/net.c +++ util/net.c @@ -56,6 +56,7 @@ * networking types here. */ NETWORK_TYPE( TCPIP ); +NETWORK_TYPE( UDPTCPIP ); NETWORK_TYPE( Devnull ); NETWORK_TYPE( File ); #ifdef GM_SUPPORT @@ -99,10 +100,14 @@ conn->port = port; conn->Alloc = NULL; /* How do we allocate buffers to send? */ conn->Send = NULL; /* How do we send things? */ + conn->Barf = NULL; /* How do we barf things? */ conn->Free = NULL; /* How do we free things? */ conn->tcp_socket = 0; + conn->udp_socket = 0; + crMemset(&conn->remoteaddr, 0, sizeof(conn->remoteaddr)); conn->gm_node_id = 0; conn->mtu = mtu; + conn->buffer_size = mtu; conn->broker = broker; conn->swap = 0; conn->endianness = crDetermineEndianness(); @@ -139,6 +144,11 @@ crTCPIPInit( cr_net.recv, cr_net.close, mtu ); crTCPIPConnection( conn ); } + else if ( !crStrcmp( protocol, "udptcpip" ) ) + { + crUDPTCPIPInit( cr_net.recv, cr_net.close, mtu ); + crUDPTCPIPConnection( conn ); + } else { crError( "Unknown Protocol: \"%s\"", protocol ); @@ -197,10 +207,14 @@ conn->port = port; conn->Alloc = NULL; /* How do we allocate buffers to send? */ conn->Send = NULL; /* How do we send things? */ + conn->Barf = NULL; /* How do we barf things? */ conn->Free = NULL; /* How do we receive things? */ conn->tcp_socket = 0; + conn->udp_socket = 0; + crMemset(&conn->remoteaddr, 0, sizeof(conn->remoteaddr)); conn->gm_node_id = 0; conn->mtu = mtu; + conn->buffer_size = mtu; conn->broker = broker; conn->swap = 0; conn->endianness = crDetermineEndianness(); @@ -243,6 +257,11 @@ crTCPIPInit( cr_net.recv, cr_net.close, mtu ); crTCPIPConnection( conn ); } + else if ( !crStrcmp( protocol, "udptcpip" ) ) + { + crUDPTCPIPInit( cr_net.recv, cr_net.close, mtu ); + crUDPTCPIPConnection( conn ); + } else { crError( "Unknown Protocol: \"%s\"", protocol ); @@ -331,7 +350,7 @@ if ( bufp ) { CRASSERT( start >= *bufp ); CRASSERT( (unsigned char *) start + len <= - (unsigned char *) *bufp + conn->mtu ); + (unsigned char *) *bufp + conn->buffer_size ); } #ifndef NDEBUG @@ -349,6 +368,38 @@ conn->Send( conn, bufp, start, len ); } +/* Barf a set of commands on a connection. Pretty straightforward, just + * error checking, byte counting, and a dispatch to the protocol's + * "barf" implementation. */ + +void crNetBarf( CRConnection *conn, void **bufp, + void *start, unsigned int len ) +{ + CRMessage *msg = (CRMessage *) start; + CRASSERT( conn ); + CRASSERT( len > 0 ); + CRASSERT( conn->Barf ); + if ( bufp ) { + CRASSERT( start >= *bufp ); + CRASSERT( (unsigned char *) start + len <= + (unsigned char *) *bufp + conn->buffer_size ); + } + +#ifndef NDEBUG + if ( conn->send_credits > CR_INITIAL_RECV_CREDITS ) + { + crError( "crNetBarf: send_credits=%u, looks like there is a " + "leak (max=%u)", conn->send_credits, + CR_INITIAL_RECV_CREDITS ); + } +#endif + + conn->total_bytes += len; + + msg->header.conn_id = conn->id; + conn->Barf( conn, bufp, start, len ); +} + /* Send something exact on a connection without the message length * header. */ @@ -632,6 +683,7 @@ int found_work = 0; found_work += crTCPIPRecv( ); + found_work += crUDPTCPIPRecv( ); found_work += crFileRecv( ); #ifdef GM_SUPPORT if ( cr_net.use_gm ) @@ -665,8 +717,6 @@ CRConnection *__copy_of_crMothershipConnect( void ) { char *mother_server = NULL; - int mother_port = MOTHERPORT; - char mother_url[1024]; crNetInit( NULL, NULL ); @@ -677,9 +727,7 @@ mother_server = "localhost"; } - sprintf( mother_url, "%s:%d", mother_server, mother_port ); - - return crNetConnectToServer( mother_server, 10000, 8096, 0 ); + return crNetConnectToServer( mother_server, MOTHERPORT, 8096, 0 ); } /* More code-copying lossage. I sure hope no one ever sees this code. Ever. */ --- util/tcpip.c +++ util/tcpip.c @@ -4,6 +4,7 @@ * See the file LICENSE.txt for information on redistributing this software. */ +#define PF PF_UNSPEC #ifdef WINDOWS #define WIN32_LEAN_AND_MEAN #pragma warning( push, 3 ) @@ -178,7 +179,7 @@ CRSocket server_sock; } cr_tcpip; -static int __read_exact( CRSocket sock, void *buf, unsigned int len ) +int __read_exact( CRSocket sock, void *buf, unsigned int len ) { char *dst = (char *) buf; @@ -234,8 +235,9 @@ } } -static int __write_exact( CRSocket sock, void *buf, unsigned int len ) +int __write_exact( CRSocket sock, void *buf, unsigned int len ) { + int err; char *src = (char *) buf; while ( len > 0 ) @@ -243,13 +245,13 @@ int num_written = write( sock, src, len ); if ( num_written <= 0 ) { - if ( crTCPIPErrno( ) == EINTR ) + if ( (err = crTCPIPErrno( )) == EINTR ) { crWarning( "__write_exact(TCPIP): " "caught an EINTR, continuing" ); continue; } - return -1; + return -err; } len -= num_written; @@ -275,7 +277,7 @@ * 1) Change the size of the send/receive buffers to 64K * 2) Turn off Nagle's algorithm */ -static void __crSpankSocket( CRSocket sock ) +void __crSpankSocket( CRSocket sock ) { int sndbuf = 64*1024; int rcvbuf = sndbuf; @@ -323,11 +325,9 @@ void crTCPIPAccept( CRConnection *conn, unsigned short port ) { int err; - struct sockaddr_in servaddr; - struct sockaddr addr; - socklen_t addr_length; - struct hostent *host; - struct in_addr sin_addr; + struct sockaddr_storage addr; + socklen_t addr_length; + char host[NI_MAXHOST]; static unsigned short last_port = 0; @@ -336,31 +336,54 @@ /* with the new OOB stuff, we can have multiple ports being * accepted on, so we need to redo the server socket every time. */ + char port_s[NI_MAXSERV]; + struct addrinfo *res,*cur; + struct addrinfo hints; - cr_tcpip.server_sock = socket( AF_INET, SOCK_STREAM, 0 ); - if ( cr_tcpip.server_sock == -1 ) - { - err = crTCPIPErrno( ); - crError( "Couldn't create socket: %s", crTCPIPErrorString( err ) ); - } - __crSpankSocket( cr_tcpip.server_sock ); + sprintf(port_s, "%u", (short unsigned) port); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = INADDR_ANY; - servaddr.sin_port = htons( port ); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = PF; + hints.ai_socktype = SOCK_STREAM; - if ( bind( cr_tcpip.server_sock, (struct sockaddr *) &servaddr, sizeof(servaddr) ) ) - { - err = crTCPIPErrno( ); - crError( "Couldn't bind to socket (port=%d): %s", port, crTCPIPErrorString( err ) ); - } - last_port = port; + err = getaddrinfo( NULL, port_s, &hints, &res ); + if ( err ) + crError( "Couldn't find local TCP port %s: %s", port_s, gai_strerror(err) ); - if ( listen( cr_tcpip.server_sock, 100 /* max pending connections */ ) ) + for (cur=res;cur;cur=cur->ai_next) { - err = crTCPIPErrno( ); - crError( "Couldn't listen on socket: %s", crTCPIPErrorString( err ) ); + cr_tcpip.server_sock = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( cr_tcpip.server_sock == -1 ) + { + err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "Couldn't create socket of family %i: %s, trying another", cur->ai_family, crTCPIPErrorString( err ) ); + continue; + } + __crSpankSocket( cr_tcpip.server_sock ); + + if ( bind( cr_tcpip.server_sock, cur->ai_addr, cur->ai_addrlen ) ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't bind to socket (port=%d): %s", port, crTCPIPErrorString( err ) ); + crCloseSocket( cr_tcpip.server_sock ); + continue; + } + last_port = port; + + if ( listen( cr_tcpip.server_sock, 100 /* max pending connections */ ) ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't listen on socket: %s", crTCPIPErrorString( err ) ); + crCloseSocket( cr_tcpip.server_sock ); + continue; + } + break; } + freeaddrinfo(res); + if (!cur) + crError( "Couldn't find local TCP port %s", port_s); } if (conn->broker) @@ -393,17 +416,24 @@ err = crTCPIPErrno( ); crError( "Couldn't accept client: %s", crTCPIPErrorString( err ) ); } - sin_addr = ((struct sockaddr_in *) &addr)->sin_addr; - host = gethostbyaddr( (char *) &sin_addr, sizeof( sin_addr), AF_INET ); - if (host == NULL ) - { - char *temp = inet_ntoa( sin_addr ); - conn->hostname = crStrdup( temp ); + + err = getnameinfo ( (struct sockaddr *) &addr, addr_length, + host, sizeof( host), + NULL, 0, NI_NAMEREQD); + if ( err ) + { + err = getnameinfo ( (struct sockaddr *) &addr, addr_length, + host, sizeof( host), + NULL, 0, NI_NUMERICHOST); + if ( err ) + conn->hostname = "unknown !"; + else + conn->hostname = crStrdup( host ); } else { char *temp; - conn->hostname = crStrdup( host->h_name ); + conn->hostname = crStrdup( host ); temp = conn->hostname; while (*temp && *temp != '.' ) @@ -427,13 +457,13 @@ if ( buf == NULL ) { crDebug( "Buffer pool was empty, so I allocated %d bytes", - (unsigned int)sizeof(CRTCPIPBuffer) + conn->mtu ); + (unsigned int)sizeof(CRTCPIPBuffer) + conn->buffer_size ); buf = (CRTCPIPBuffer *) - crAlloc( sizeof(CRTCPIPBuffer) + conn->mtu ); + crAlloc( sizeof(CRTCPIPBuffer) + conn->buffer_size ); buf->magic = CR_TCPIP_BUFFER_MAGIC; buf->kind = CRTCPIPMemory; buf->pad = 0; - buf->allocated = conn->mtu; + buf->allocated = conn->buffer_size; } #ifdef CHROMIUM_THREADSAFE @@ -456,14 +486,11 @@ if ( bufp == NULL ) { + unsigned int len_swap = conn->swap ? SWAP32(len) : len; /* we are doing synchronous sends from user memory, so no need * to get fancy. Simply write the length & the payload and * return. */ - if (conn->swap) - { - len = SWAP32(len); - } - crTCPIPWriteExact( conn, &len, sizeof(len) ); + crTCPIPWriteExact( conn, &len_swap, sizeof(len_swap) ); crTCPIPWriteExact( conn, start, len ); return; } @@ -504,14 +531,14 @@ *bufp = NULL; } -static void __dead_connection( CRConnection *conn ) +void __dead_connection( CRConnection *conn ) { crWarning( "Dead connection (sock=%d, host=%s)", conn->tcp_socket, conn->hostname ); exit( 0 ); } -static int __crSelect( int n, fd_set *readfds, struct timeval *timeout ) +int __crSelect( int n, fd_set *readfds, struct timeval *timeout ) { for ( ; ; ) { @@ -594,7 +621,7 @@ * (MSG_PEEK flag to recv()?) if the connection isn't * enabled. */ - struct sockaddr s; + struct sockaddr_storage s; socklen_t slen; fd_set only_fd; /* testing single fd */ CRSocket sock = conn->tcp_socket; @@ -626,7 +653,7 @@ FD_SET( sock, &only_fd ); slen = sizeof( s ); /* Check that the socket is REALLY connected */ - if (getpeername(sock, &s, &slen) < 0) { + if (getpeername(sock, (struct sockaddr *) &s, &slen) < 0) { FD_CLR(sock, &read_fds); msock = sock; } @@ -700,7 +727,7 @@ CRASSERT( len > 0 ); - if ( len <= conn->mtu ) + if ( len <= conn->buffer_size ) { tcpip_buffer = (CRTCPIPBuffer *) crTCPIPAlloc( conn ) - 1; } @@ -821,36 +848,24 @@ int crTCPIPDoConnect( CRConnection *conn ) { - struct sockaddr_in servaddr; - struct hostent *hp; + char port_s[NI_MAXSERV]; + struct addrinfo *res,*cur; + struct addrinfo hints; int err; - conn->tcp_socket = socket( AF_INET, SOCK_STREAM, 0 ); - if ( conn->tcp_socket < 0 ) - { - int err = crTCPIPErrno( ); - crWarning( "socket error: %s", crTCPIPErrorString( err ) ); - return 0; - } + sprintf(port_s, "%u", (short unsigned) conn->port); - /* Set up the socket the way *we* want. */ - __crSpankSocket( conn->tcp_socket ); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF; + hints.ai_socktype = SOCK_STREAM; - /* Standard Berkeley sockets mumbo jumbo */ - hp = gethostbyname( conn->hostname ); - if ( !hp ) + err = getaddrinfo( conn->hostname, port_s, &hints, &res); + if ( err ) { - crWarning( "Unknown host: \"%s\"", conn->hostname ); + crWarning( "Unknown host: \"%s\": %s", conn->hostname, gai_strerror(err) ); return 0; } - memset( &servaddr, 0, sizeof(servaddr) ); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons( (short) conn->port ); - - memcpy( (char *) &servaddr.sin_addr, hp->h_addr, - sizeof(servaddr.sin_addr) ); - if (conn->broker) { CRConnection *mother; @@ -860,10 +875,11 @@ if (!__copy_of_crMothershipSendString( mother, response, "connectrequest tcpip %s %d %d", conn->hostname, conn->port, conn->endianness) ) { + freeaddrinfo(res); crError( "Mothership didn't like my connect request request" ); } - __copy_of_crMothershipDisconnect( mother ); + __copy_of_crMothershipDisconnect( mother ); sscanf( response, "%d %d", &(conn->id), &(remote_endianness) ); @@ -872,34 +888,46 @@ conn->swap = 1; } } - for (;;) + for (cur=res;cur;) { - if ( !connect( conn->tcp_socket, (struct sockaddr *) &servaddr, - sizeof(servaddr) ) ) - break; + conn->tcp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( conn->tcp_socket < 0 ) + { + int err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "socket error: %s, trying another way", crTCPIPErrorString( err ) ); + cur=cur->ai_next; + continue; + } + + /* Set up the socket the way *we* want. */ + __crSpankSocket( conn->tcp_socket ); + + if ( !connect( conn->tcp_socket, cur->ai_addr, cur->ai_addrlen ) ) { + freeaddrinfo(res); + return 1; + } + crCloseSocket( conn->tcp_socket ); err = crTCPIPErrno( ); if ( err == EADDRINUSE || err == ECONNREFUSED ) - { - /* Here's where we might try again on another - * port -- don't think we'll do that any more. */ crWarning( "Couldn't connect to %s:%d, %s", conn->hostname, conn->port, crTCPIPErrorString( err ) ); - return 0; - } + else if ( err == EINTR ) { crWarning( "connection to %s:%d " "interruped, trying again", conn->hostname, conn->port ); + continue; } else - { crWarning( "Couldn't connect to %s:%d, %s", conn->hostname, conn->port, crTCPIPErrorString( err ) ); - return 0; - } + cur=cur->ai_next; } - return 1; + freeaddrinfo(res); + crWarning( "Couln't find any suitable way to connect to %s", conn->hostname ); + return 0; } void crTCPIPDoDisconnect( CRConnection *conn ) --- /dev/null +++ util/udptcpip.c @@ -0,0 +1,1063 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#define PF PF_UNSPEC +#ifdef WINDOWS +#define WIN32_LEAN_AND_MEAN +#pragma warning( push, 3 ) +#include +#pragma warning( pop ) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4127 ) +typedef int ssize_t; +#define write(a,b,c) send(a,b,c,0) +#else +#include +#ifdef DARWIN +typedef unsigned int socklen_t; +#endif +#include +#include +#include +#ifdef LINUX +#define IP_MTU 14 +#endif +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#ifdef AIX +#include +#endif + +#include "cr_error.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "cr_bufpool.h" +#include "cr_net.h" +#include "cr_endian.h" +#include "cr_threads.h" +#include "net_internals.h" + +#ifdef WINDOWS +#define EADDRINUSE WSAEADDRINUSE +#define ECONNREFUSED WSAECONNREFUSED +#endif + +typedef enum { + CRUDPTCPIPMemory, + CRUDPTCPIPMemoryBig +} CRUDPTCPIPBufferKind; + +#define CR_UDPTCPIP_BUFFER_MAGIC 0x89134532 + +typedef struct CRUDPTCPIPBuffer { + unsigned int magic; + CRUDPTCPIPBufferKind kind; + unsigned int len; + unsigned int allocated; + unsigned int pad; +} CRUDPTCPIPBuffer; + + +/* Forward decl */ +static void crUDPTCPIPFree( CRConnection *conn, void *buf ); + +#ifdef WINDOWS + +#undef ECONNRESET +#define ECONNRESET WSAECONNRESET +#undef EINTR +#define EINTR WSAEINTR + +#endif +extern int crTCPIPErrno( void ); +extern char *crTCPIPErrorString( int err ); + +extern void crCloseSocket( CRSocket sock ); + +extern int crSameAddr(struct sockaddr *addr1, struct sockaddr *addr2); + +static struct { + int initialized; + int num_conns; + CRConnection **conns; + CRBufferPool bufpool; +#ifdef CHROMIUM_THREADSAFE + CRmutex mutex; + CRmutex recvmutex; +#endif + CRNetReceiveFunc recv; + CRNetCloseFunc close; + CRSocket server_sock; +} cr_udptcpip; + +extern int __read_exact( CRSocket sock, void *buf, unsigned int len ); +extern void crTCPIPReadExact( CRSocket sock, void *buf, unsigned int len ); +extern int __write_exact( CRSocket sock, void *buf, unsigned int len ); +extern void crTCPIPSend( CRConnection *conn, void **bufp, void *start, unsigned int len ); +extern void crTCPIPWriteExact( CRConnection *conn, void *buf, unsigned int len ); +extern void __crSpankSocket( CRSocket sock ); + +#if defined( WINDOWS ) || defined( IRIX ) || defined( IRIX64 ) +typedef int socklen_t; +#endif + +void crUDPIPWriteExact( CRConnection *conn, void *buf, unsigned int len ) +{ + int retval; + if ( len > conn->mtu + sizeof(conn->seq) ) + { + crWarning( "crUDPIPWriteExact(%d): too big a packet for mtu %d, dropping !", len, conn->mtu + sizeof(conn->seq) ); + return; + } + retval = sendto( conn->udp_socket, buf, len, 0, + (struct sockaddr *) &(conn->remoteaddr), sizeof(conn->remoteaddr)); + if ( retval <= 0 ) + { + int err = crTCPIPErrno( ); + //crError( "crUDPIPWriteExact(%d): %s", len, crTCPIPErrorString( err ) ); + crWarning( "crUDPIPWriteExact(%d): %s", len, crTCPIPErrorString( err ) ); +#ifdef LINUX + if ( err == EMSGSIZE ) + { + int opt; + socklen_t leno = sizeof(opt); + crDebug( "Too big a UDP packet(%d), looking at new MTU...", len ); + if ( getsockopt( conn->udp_socket, SOL_IP, IP_MTU_DISCOVER, &opt, &leno) == -1) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't determine whether PMTU discovery is used : %s", crTCPIPErrorString( err ) ); + return; + } + if ( leno != sizeof(opt) ) + { + crWarning( "Unexpected length %d for PMTU_DISCOVERY option length", leno ); + return; + } + if ( opt == IP_PMTUDISC_DONT ) + { + crWarning( "Uh, PMTU discovery isn't enabled ?!" ); + return; + } + if ( getsockopt( conn->udp_socket, SOL_IP, IP_MTU, &opt, &leno) == -1 ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't determine the MTU : %s", crTCPIPErrorString( err ) ); + return; + } + if ( leno != sizeof(opt) ) + { + crWarning( "Unexpected length %d for MTU option length", leno ); + return; + } + opt -= sizeof(conn->seq) + sizeof(struct udphdr) + sizeof(struct ip6_hdr); + if (opt >= conn->mtu) + { + crWarning( "But MTU discovery is still bigger ! Narrowing it by hand to %d", conn->mtu = (conn->mtu * 2 / 3) & ~0x3 ); + } + else + { + crDebug( "new MTU is %d", opt ); + conn->mtu = opt & ~0x3; + } + } +#endif + } +} + +static void crUDPTCPIPAccept( CRConnection *conn, unsigned short port ) +{ + int err; + struct sockaddr_storage addr; + socklen_t addr_length; + char host[NI_MAXHOST]; + struct addrinfo *res,*cur; + struct addrinfo hints; + + static unsigned short last_port = 0; + + if (port != last_port) + { + /* with the new OOB stuff, we can have multiple ports being + * accepted on, so we need to redo the server socket every time. + */ + char port_s[NI_MAXSERV]; + + sprintf(port_s, "%u", (short unsigned) port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = PF; + hints.ai_socktype = SOCK_STREAM; + + err = getaddrinfo( NULL, port_s, &hints, &res); + if ( err ) + crError( "Couldn't find local TCP port %s: %s", port_s, gai_strerror(err)); + + for (cur=res;cur;cur=cur->ai_next) + { + cr_udptcpip.server_sock = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( cr_udptcpip.server_sock == -1 ) + { + err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "Couldn't create socket of family %i: %s, trying another", cur->ai_family, crTCPIPErrorString( err ) ); + continue; + } + __crSpankSocket( cr_udptcpip.server_sock ); + + if ( bind( cr_udptcpip.server_sock, cur->ai_addr, cur->ai_addrlen ) ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't bind to socket (port=%d): %s", port, crTCPIPErrorString( err ) ); + crCloseSocket( cr_udptcpip.server_sock ); + continue; + } + last_port = port; + + if ( listen( cr_udptcpip.server_sock, 100 /* max pending connections */ ) ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't listen on socket: %s", crTCPIPErrorString( err ) ); + crCloseSocket( cr_udptcpip.server_sock ); + continue; + } + break; + } + freeaddrinfo(res); + if (!cur) + crError( "Couldn't find local TCP port %s", port_s); + } + + if (conn->broker) + { + CRConnection *mother; + char response[8096]; + char my_hostname[256]; + + mother = __copy_of_crMothershipConnect( ); + + if ( crGetHostname( my_hostname, sizeof( my_hostname ) ) ) + { + crError( "Couldn't determine my own hostname in crUDPTCPIPAccept!" ); + } + + if (!__copy_of_crMothershipSendString( mother, response, "acceptrequest udptcpip %s %d %d", my_hostname, conn->port, conn->endianness ) ) + { + crError( "Mothership didn't like my accept request request" ); + } + + __copy_of_crMothershipDisconnect( mother ); + + sscanf( response, "%d", &(conn->id) ); + } + + addr_length = sizeof( addr ); + conn->tcp_socket = accept( cr_udptcpip.server_sock, (struct sockaddr *) &addr, &addr_length ); + if (conn->tcp_socket == -1) + { + err = crTCPIPErrno( ); + crError( "Couldn't accept client: %s", crTCPIPErrorString( err ) ); + } + + err = getnameinfo ( (struct sockaddr *) &addr, addr_length, + host, sizeof( host), + NULL, 0, NI_NAMEREQD); + if ( err ) + { + err = getnameinfo ( (struct sockaddr *) &addr, addr_length, + host, sizeof( host), + NULL, 0, NI_NUMERICHOST); + if ( err ) + conn->hostname = "unknown !"; + else + conn->hostname = crStrdup( host ); + } + else + { + char *temp; + conn->hostname = crStrdup( host ); + + temp = conn->hostname; + while (*temp && *temp != '.' ) + temp++; + *temp = '\0'; + } + + crDebug( "Accepted connection from \"%s\".", conn->hostname ); + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = PF; + hints.ai_socktype = SOCK_DGRAM; + + err = getaddrinfo( NULL, "0", &hints, &res); + if ( err ) + crError( "Couldn't find local UDP port: %s", gai_strerror(err)); + + conn->udp_socket = -1; + + for (cur=res;cur;cur=cur->ai_next) + { + conn->udp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( conn->udp_socket == -1 ) + { + err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "Couldn't create socket of family %i: %s, trying another one", cur->ai_family, crTCPIPErrorString( err ) ); + continue; + } + if ( bind( conn->udp_socket, cur->ai_addr, cur->ai_addrlen ) ) + { + err = crTCPIPErrno( ); + crWarning( "Couldn't bind socket: %s", crTCPIPErrorString( err ) ); + crCloseSocket( conn->udp_socket ); + conn->udp_socket = -1; + continue; + } + break; + + } + + freeaddrinfo(res); + + if ( conn->udp_socket < 0 ) + crError( "Couldn't find local UDP port" ); + + addr_length = sizeof(addr); + err = getsockname( conn->udp_socket, (struct sockaddr *) &addr, &addr_length ); + + if ( err == -1 ) + crError( "Couldn't get our local UDP port: %s", crTCPIPErrorString( err ) ); + + switch (((struct sockaddr *) &addr)->sa_family) { + case AF_INET: + crTCPIPWriteExact( conn, &((struct sockaddr_in *)&addr)->sin_port, + sizeof(((struct sockaddr_in *)&addr)->sin_port)); + break; + case AF_INET6: + crTCPIPWriteExact( conn, &((struct sockaddr_in6 *)&addr)->sin6_port, + sizeof(((struct sockaddr_in6 *)&addr)->sin6_port)); + break; + default: + crError( "Unknown address family: %d", ((struct sockaddr *) &addr)->sa_family); + } +} + +void *crUDPTCPIPAlloc( CRConnection *conn ) +{ + CRUDPTCPIPBuffer *buf; + +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&cr_udptcpip.mutex); +#endif + + buf = (CRUDPTCPIPBuffer *) crBufferPoolPop( &cr_udptcpip.bufpool ); + + if ( buf == NULL ) + { + crDebug( "Buffer pool was empty, so I allocated %d bytes", + (unsigned int)sizeof(CRUDPTCPIPBuffer) + conn->buffer_size ); + buf = (CRUDPTCPIPBuffer *) + crAlloc( sizeof(CRUDPTCPIPBuffer) + conn->buffer_size ); + buf->magic = CR_UDPTCPIP_BUFFER_MAGIC; + buf->kind = CRUDPTCPIPMemory; + buf->pad = 0; + buf->allocated = conn->buffer_size; + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.mutex); +#endif + + return (void *)( buf + 1 ); +} + +static unsigned long long safelen=0; +static void crUDPTCPIPSend( CRConnection *conn, void **bufp, + void *start, unsigned int len ) +{ + static unsigned long long safeblip=0; + CRUDPTCPIPBuffer *udptcpip_buffer; + unsigned int *lenp; + + safelen+=len; + if (safelen-safeblip>100000) + { + safeblip=safelen; + crDebug( "%lldKo safe", safelen/(1LL<<10) ); + } + + conn->seq++; + //crDebug("sendseq++ -> %u", conn->seq); + if (len <= conn->mtu) + { + //unsigned char *c; + if (len>1000) { + crDebug("writing safely %d bytes",len); + /*for (c=start;len;c++,len--) + fprintf(stderr,"%3d ",*c); + fprintf(stderr,"\n");*/ + } + } else { + crDebug("writing big packet %d", len); + } + + if ( bufp == NULL ) + { + unsigned int len_swap = conn->swap ? SWAP32(len) : len; + /* we are doing synchronous sends from user memory, so no need + * to get fancy. Simply write the length & the payload and + * return. */ + crTCPIPWriteExact( conn, &len_swap, sizeof(len_swap) ); + crTCPIPWriteExact( conn, start, len ); + return; + } + + udptcpip_buffer = (CRUDPTCPIPBuffer *)(*bufp) - 1; + + CRASSERT( udptcpip_buffer->magic == CR_UDPTCPIP_BUFFER_MAGIC ); + + /* All of the buffers passed to the send function were allocated + * with crTCPIPAlloc(), which includes a header with a 4 byte + * length field, to insure that we always have a place to write + * the length field, even when start == *bufp. */ + lenp = (unsigned int *) start - 1; + if (conn->swap) + { + *lenp = SWAP32(len); + } + else + { + *lenp = len; + } + + if ( __write_exact( conn->tcp_socket, lenp, len + sizeof(*lenp) ) < 0 ) + { + int err = crTCPIPErrno( ); + crError( "crUDPTCPIPSend: %s", crTCPIPErrorString( err ) ); + } + + /* reclaim this pointer for reuse and try to keep the client from + accidentally reusing it directly */ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&cr_udptcpip.mutex); +#endif + crBufferPoolPush( &cr_udptcpip.bufpool, udptcpip_buffer ); +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.mutex); +#endif + *bufp = NULL; +} + +static unsigned long long barflen=0; +static void crUDPTCPIPBarf( CRConnection *conn, void **bufp, + void *start, unsigned int len) +{ + static unsigned long long barfblip=0; + static const unsigned int sizes[]={ + 0,10,50,100,500,1000,5000,10000,UINT_MAX + }; + static unsigned long long nbs[sizeof(sizes)/sizeof(int)] = { [sizeof(sizes)/sizeof(int)-1] 0 }; + static unsigned long long nb; + unsigned int *seqp; + CRUDPTCPIPBuffer *udptcpip_buffer; + int i; + + if (!bufp) { + crDebug("writing safely %d bytes because from user memory",len); + return crUDPTCPIPSend( conn, bufp, start, len); + } + if (len > conn->mtu) { + crDebug("writing safely %d bytes because that is too much for MTU %d", len, conn->mtu); + return crUDPTCPIPSend( conn, bufp, start, len); + } + + barflen+=len; + nb++; + for(i=0;;i++) + if (len > sizes[i] && len <= sizes[(i+1)]) { + nbs[i]++; + break; + } + if (barflen-barfblip>1<<22) { + barfblip=barflen; + crDebug( "send traffic: %lld%sMo barfed %lldKo safe", barflen/(1LL<<20), barflen?"":".0", safelen/(1LL<<10) ); + if (nb) { + for (i=0;imagic == CR_UDPTCPIP_BUFFER_MAGIC ); + + seqp = (unsigned int *) start - 1; + if (conn->swap) + { + *seqp = SWAP32(conn->seq); + } + else + { + *seqp = conn->seq; + } + //if (random()%2) + crUDPIPWriteExact( conn, seqp, len + sizeof(*seqp) ); + /*else { + unsigned char *c; + crDebug("dropped packet of length %d", len); + for (c=start;len;c++,len--) + fprintf(stderr,"%3d ",*c); + fprintf(stderr,"\n"); + }*/ + //crDebug("sendseq : %u", conn->seq); + + /* reclaim this pointer for reuse and try to keep the client from + accidentally reusing it directly */ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&cr_udptcpip.mutex); +#endif + crBufferPoolPush( &cr_udptcpip.bufpool, udptcpip_buffer ); +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.mutex); +#endif + *bufp = NULL; +} + +extern void __dead_connection( CRConnection *conn ); +extern int __crSelect( int n, fd_set *readfds, struct timeval *timeout ); + +static void crUDPTCPIPFree( CRConnection *conn, void *buf ) +{ + CRUDPTCPIPBuffer *udptcpip_buffer = (CRUDPTCPIPBuffer *) buf - 1; + + CRASSERT( udptcpip_buffer->magic == CR_UDPTCPIP_BUFFER_MAGIC ); + conn->recv_credits += udptcpip_buffer->len; + + switch ( udptcpip_buffer->kind ) + { + case CRUDPTCPIPMemory: +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&cr_udptcpip.mutex); +#endif + crBufferPoolPush( &cr_udptcpip.bufpool, udptcpip_buffer ); +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.mutex); +#endif + break; + + case CRUDPTCPIPMemoryBig: + crFree( udptcpip_buffer ); + break; + + default: + crError( "Weird buffer kind trying to free in crUDPTCPIPFree: %d", udptcpip_buffer->kind ); + } +} + +static void crUDPTCPIPReceive( CRConnection *conn, CRUDPTCPIPBuffer *buf, int len ) +{ + CRMessage *msg; + CRMessageType cached_type; +#if 0 + crLogRead( len ); +#endif + + conn->recv_credits -= len; + + msg = (CRMessage *) (buf + 1); + cached_type = msg->header.type; + if (conn->swap) + { + msg->header.type = (CRMessageType) SWAP32( msg->header.type ); + msg->header.conn_id = (CRMessageType) SWAP32( msg->header.conn_id ); + } + if (!cr_udptcpip.recv( conn, buf + 1, len )) + { + crNetDefaultRecv( conn, buf + 1, len ); + } + + /* CR_MESSAGE_OPCODES is freed in + * crserver/server_stream.c + * + * OOB messages are the programmer's problem. -- Humper 12/17/01 */ + if (cached_type != CR_MESSAGE_OPCODES && cached_type != CR_MESSAGE_OOB) + { + crUDPTCPIPFree( conn, buf + 1 ); + } +} + +int crUDPTCPIPRecv( void ) +{ + int num_ready, max_fd; + fd_set read_fds; + int i; + //int msock = -1; /* assumed mothership socket */ + /* ensure we don't get caught with a new thread connecting */ + int num_conns = cr_udptcpip.num_conns; + +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&cr_udptcpip.recvmutex); +#endif + + max_fd = 0; + FD_ZERO( &read_fds ); + for ( i = 0; i < num_conns; i++ ) + { + CRConnection *conn = cr_udptcpip.conns[i]; + if (!conn) continue; + if ( conn->recv_credits > 0 || conn->type != CR_UDPTCPIP ) + { + /* + * NOTE: may want to always put the FD in the descriptor + * set so we'll notice broken connections. Down in the + * loop that iterates over the ready sockets only peek + * (MSG_PEEK flag to recv()?) if the connection isn't + * enabled. + */ + CRSocket sock = conn->tcp_socket; + + if ( (int) sock + 1 > max_fd ) + max_fd = (int) sock + 1; + FD_SET( sock, &read_fds ); + + sock = conn->udp_socket; + if ( (int) sock + 1 > max_fd ) + max_fd = (int) sock + 1; + FD_SET( sock, &read_fds ); + } + } + + if (!max_fd) { +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.recvmutex); +#endif + return 0; + } + + if ( num_conns ) + { + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 500; + num_ready = __crSelect( max_fd, &read_fds, &timeout ); + } + else + { + crWarning( "Waiting for first connection..." ); + num_ready = __crSelect( max_fd, &read_fds, NULL ); + } + + if ( num_ready == 0 ) { +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.recvmutex); +#endif + return 0; + } + + for ( i = 0; i < num_conns; i++ ) + { + CRConnection *conn = cr_udptcpip.conns[i]; + CRUDPTCPIPBuffer *buf; + int read_ret; + int len; + int sock; + + if (!conn) continue; + + if ( conn->udp_packet ) { + unsigned int *seq; + buf = conn->udp_packet; + seq = (unsigned int *)(buf + 1) - 1; + if ( *seq == conn->seq ) + { + //crDebug( "seq == conn->seq == %u, ok, can go on", *seq ); + crUDPTCPIPReceive( conn, buf, + conn->udp_packetlen ); + conn->udp_packet = NULL; + i--; // can now read other packets + continue; + } + if ( *seq - conn->seq > (~(0U)) >> 1 ) + { + crWarning( "%u is older than %u, dropping", *seq, conn->seq ); + crUDPTCPIPFree( conn, buf ); + continue; + } + } + else if ( FD_ISSET(conn->udp_socket, &read_fds ) ) + { + CRUDPTCPIPBuffer *buf = ((CRUDPTCPIPBuffer *) crUDPTCPIPAlloc( conn )) - 1; + unsigned int *seq = ((unsigned int *) (buf + 1)) - 1; + int len; + FD_CLR( conn->udp_socket, &read_fds ); + + len = recv( conn->udp_socket, seq, + buf->allocated + sizeof(*seq), MSG_TRUNC ); + + CRASSERT( len > 0 ); + CRASSERT( len <= buf->allocated + sizeof(*seq) ); + if ( len < sizeof(*seq) ) + { + crWarning( "too short a UDP packet : %d", len); + crUDPTCPIPFree( conn, buf ); + continue; + } + + buf->len = len; + + if ( *seq == conn->seq) + { + //crDebug( "seq == conn->seq == %u, ok, can go on", *seq ); + crUDPTCPIPReceive( conn, buf, len ); + continue; + } + + if ( *seq - conn->seq > (~(0U)) >> 1 ) + { + crWarning( "%u is older than %u, dropping", *seq, conn->seq ); + crUDPTCPIPFree( conn, buf ); + continue; + } + //crDebug( "oh, so seq increased (now %d, should become %d), let's see that", conn->seq, *seq ); + conn->udp_packet = buf; + conn->udp_packetlen = len; + } + + sock = conn->tcp_socket; + if ( !FD_ISSET( sock, &read_fds ) ) + continue; + + read_ret = __read_exact( sock, &len, sizeof(len) ); + if ( read_ret <= 0 ) + { + __dead_connection( conn ); + i--; + continue; + } + + if (conn->swap) + { + len = SWAP32(len); + } + + CRASSERT( len > 0 ); + + if ( len <= conn->buffer_size ) + { + buf = (CRUDPTCPIPBuffer *) crUDPTCPIPAlloc( conn ) - 1; + } + else + { + buf = (CRUDPTCPIPBuffer *) + crAlloc( sizeof(*buf) + len ); + buf->magic = CR_UDPTCPIP_BUFFER_MAGIC; + buf->kind = CRUDPTCPIPMemoryBig; + buf->pad = 0; + } + + buf->len = len; + + read_ret = __read_exact( sock, buf + 1, len ); + if ( read_ret <= 0 ) + { + crWarning( "Bad juju: %d %d", buf->allocated, len ); + crFree( buf ); + __dead_connection( conn ); + i--; + continue; + } + + crUDPTCPIPReceive( conn, buf, len ); + // and increment sequence number + conn->seq++; + //crDebug( "seq is now %u", conn->seq ); + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&cr_udptcpip.recvmutex); +#endif + + return 1; +} + +static void crUDPTCPIPHandleNewMessage( CRConnection *conn, CRMessage *msg, + unsigned int len ) +{ + CRUDPTCPIPBuffer *buf = ((CRUDPTCPIPBuffer *) msg) - 1; + + /* build a header so we can delete the message later */ + buf->magic = CR_UDPTCPIP_BUFFER_MAGIC; + buf->kind = CRUDPTCPIPMemory; + buf->len = len; + buf->pad = 0; + + if (!cr_udptcpip.recv( conn, msg, len )) + { + crNetDefaultRecv( conn, msg, len ); + } +} + +static void crUDPTCPIPInstantReclaim( CRConnection *conn, CRMessage *mess ) +{ + crUDPTCPIPFree( conn, mess ); +} + +void crUDPTCPIPInit( CRNetReceiveFunc recvFunc, CRNetCloseFunc closeFunc, unsigned int mtu ) +{ + (void) mtu; + if ( cr_udptcpip.initialized ) + { + if ( cr_udptcpip.recv == NULL && cr_udptcpip.close == NULL ) + { + cr_udptcpip.recv = recvFunc; + cr_udptcpip.close = closeFunc; + } + else + { + CRASSERT( cr_udptcpip.recv == recvFunc ); + CRASSERT( cr_udptcpip.close == closeFunc ); + } + return; + } + + cr_udptcpip.num_conns = 0; + cr_udptcpip.conns = NULL; + + cr_udptcpip.server_sock = -1; + +#ifdef CHROMIUM_THREADSAFE + crInitMutex(&cr_udptcpip.mutex); + crInitMutex(&cr_udptcpip.recvmutex); +#endif + crBufferPoolInit( &cr_udptcpip.bufpool, 16 ); + + cr_udptcpip.recv = recvFunc; + cr_udptcpip.close = closeFunc; + + cr_udptcpip.initialized = 1; +} +/* The function that actually connects. This should only be called by clients + * Servers have another way to set up the socket. */ + +static int crUDPTCPIPDoConnect( CRConnection *conn ) +{ + char port_s[NI_MAXSERV]; + in_port_t port; + struct addrinfo *res,*cur; + struct addrinfo hints; + int err; + + // first connect to its tcp port + sprintf(port_s, "%u", (short unsigned) conn->port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF; + hints.ai_socktype = SOCK_STREAM; + + err = getaddrinfo( conn->hostname, port_s, &hints, &res); + if ( err ) + { + crWarning( "Unknown host: \"%s\": %s", conn->hostname, gai_strerror(err) ); + return 0; + } + + if (conn->broker) + { + CRConnection *mother; + char response[8096]; + int remote_endianness; + mother = __copy_of_crMothershipConnect( ); + + if (!__copy_of_crMothershipSendString( mother, response, "connectrequest udptcpip %s %d %d", conn->hostname, conn->port, conn->endianness) ) + { + freeaddrinfo(res); + crError( "Mothership didn't like my connect request request" ); + } + + __copy_of_crMothershipDisconnect( mother ); + + sscanf( response, "%d %d", &(conn->id), &(remote_endianness) ); + + if (conn->endianness != remote_endianness) + { + conn->swap = 1; + } + } + for (cur=res;cur;) + { + conn->tcp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( conn->tcp_socket < 0 ) + { + int err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "socket error: %s, trying another way", crTCPIPErrorString( err ) ); + cur=cur->ai_next; + continue; + } + + /* Set up the socket the way *we* want. */ + __crSpankSocket( conn->tcp_socket ); + + if ( !connect( conn->tcp_socket, cur->ai_addr, cur->ai_addrlen ) ) + break; + + crCloseSocket( conn->tcp_socket ); + + err = crTCPIPErrno( ); + if ( err == EADDRINUSE || err == ECONNREFUSED ) + crWarning( "Couldn't connect to %s:%d, %s", + conn->hostname, conn->port, crTCPIPErrorString( err ) ); + + else if ( err == EINTR ) + { + crWarning( "connection to %s:%d " + "interruped, trying again", conn->hostname, conn->port ); + continue; + } + else + crWarning( "Couldn't connect to %s:%d, %s", + conn->hostname, conn->port, crTCPIPErrorString( err ) ); + cur=cur->ai_next; + } + + freeaddrinfo(res); + if (!cur) { + crWarning( "Couln't find any suitable way to connect to %s", conn->hostname ); + return 0; + } + + // read its UDP port + crTCPIPReadExact( conn->tcp_socket, &port, sizeof( port ) ); + port = ntohs(port); + + crDebug( "Server's UDP port is %d", port); + + // and connect to it + sprintf(port_s, "%u", port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF; + hints.ai_socktype = SOCK_DGRAM; + + err = getaddrinfo( conn->hostname, port_s, &hints, &res); + if ( err ) + { + crWarning( "Unknown host: \"%s\": %s", conn->hostname, gai_strerror(err) ); + return 0; + } + + for (cur=res;cur;) + { + conn->udp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( conn->udp_socket >= 0 ) + { +#ifdef LINUX + int opt = IP_PMTUDISC_DO; +#endif + if ( connect( conn->udp_socket, cur->ai_addr, cur->ai_addrlen ) == -1 ) + crWarning( "Couldn't connect UDP socket : %s", crTCPIPErrorString( crTCPIPErrno( ) ) ); +#ifdef LINUX + if ( setsockopt(conn->udp_socket, SOL_IP, IP_MTU_DISCOVER, &opt, sizeof(opt)) == -1 ) + { + err = crTCPIPErrno( ); + crWarning( "MTU discovery can't be activated : %s", crTCPIPErrorString( err ) ); + } + else + { + socklen_t len = sizeof(opt); + if ( getsockopt(conn->udp_socket, SOL_IP, IP_MTU, &opt, &len) == -1 ) + crWarning( "MTU couldn't be got : %s", crTCPIPErrorString( crTCPIPErrno ( ) ) ); + else + if ( len != sizeof(opt) ) + crWarning( "Unexpected length %d for MTU option length", len ); + else + { + opt -= sizeof(conn->seq) + sizeof(struct udphdr) + sizeof(struct ip6_hdr); + crDebug( "MTU is (for now) %d", opt ); + conn->mtu = opt; + } + } +#endif + crMemcpy(&conn->remoteaddr, cur->ai_addr, cur->ai_addrlen); + freeaddrinfo(res); + return 1; + } + err = crTCPIPErrno( ); + if (err != EAFNOSUPPORT) + crWarning( "socket error: %s, trying another way", crTCPIPErrorString( err ) ); + cur=cur->ai_next; + } + freeaddrinfo(res); + crWarning( "Couldn't find any suitable way to connect to %s:%d", conn->hostname, port ); + return 0; +} + +static void crUDPTCPIPDoDisconnect( CRConnection *conn ) +{ + crCloseSocket( conn->tcp_socket ); + crCloseSocket( conn->udp_socket ); + conn->tcp_socket = 0; + conn->type = CR_NO_CONNECTION; + cr_udptcpip.conns[conn->index] = NULL; +} + +void crUDPTCPIPConnection( CRConnection *conn ) +{ + int i, found = 0; + int n_bytes; + + CRASSERT( cr_udptcpip.initialized ); + + srandom(time(NULL)); + conn->type = CR_UDPTCPIP; + conn->Alloc = crUDPTCPIPAlloc; + conn->Send = crUDPTCPIPSend; + conn->Barf = crUDPTCPIPBarf; + conn->SendExact = NULL; + conn->Recv = NULL; // none for UDP : *must* multiplex ! + conn->Free = crUDPTCPIPFree; + conn->Accept = crUDPTCPIPAccept; + conn->Connect = crUDPTCPIPDoConnect; + conn->Disconnect = crUDPTCPIPDoDisconnect; + conn->InstantReclaim = crUDPTCPIPInstantReclaim; + conn->HandleNewMessage = crUDPTCPIPHandleNewMessage; + conn->seq = 0; + conn->udp_packet = NULL; + conn->mtu = conn->mtu - sizeof(conn->seq); // some room for seq + conn->index = cr_udptcpip.num_conns; + conn->sizeof_buffer_header = sizeof( CRUDPTCPIPBuffer ); + + /* Find a free slot */ + for (i = 0; i < cr_udptcpip.num_conns; i++) { + if (cr_udptcpip.conns[i] == NULL) { + conn->index = i; + cr_udptcpip.conns[i] = conn; + found = 1; + break; + } + } + + /* Realloc connection stack if we couldn't find a free slot */ + if (found == 0) { + n_bytes = ( cr_udptcpip.num_conns + 1 ) * sizeof(*cr_udptcpip.conns); + crRealloc( (void **) &cr_udptcpip.conns, n_bytes ); + cr_udptcpip.conns[cr_udptcpip.num_conns++] = conn; + } +} --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packer/pack_beginend.c 27 Jun 2002 09:07:56 -0000 1.1 @@ -0,0 +1,67 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "packer.h" +#include "cr_protocol.h" + +void PACK_APIENTRY crPackBegin( GLenum mode ) +{ + GET_PACKER_CONTEXT(pc); + unsigned char *data_ptr; + (void) pc; + if (pc->buffer.canBarf) + { + if (!pc->buffer.holds_BeginEnd) + pc->Flush( pc->flush_arg ); + pc->buffer.in_BeginEnd = 1; + pc->buffer.holds_BeginEnd = 1; + } + GET_BUFFERED_POINTER( pc, 4 ); + pc->current.begin_data = data_ptr; + pc->current.begin_op = pc->buffer.opcode_current; + WRITE_DATA( 0, GLenum, mode ); + WRITE_OPCODE( pc, CR_BEGIN_OPCODE ); +} + +void PACK_APIENTRY crPackBeginSWAP( GLenum mode ) +{ + GET_PACKER_CONTEXT(pc); + unsigned char *data_ptr; + (void) pc; + if (pc->buffer.canBarf) + { + if (!pc->buffer.holds_BeginEnd) + pc->Flush( pc->flush_arg ); + pc->buffer.in_BeginEnd = 1; + pc->buffer.holds_BeginEnd = 1; + } + GET_BUFFERED_POINTER( pc, 4 ); + pc->current.begin_data = data_ptr; + pc->current.begin_op = pc->buffer.opcode_current; + WRITE_DATA( 0, GLenum, SWAP32(mode) ); + WRITE_OPCODE( pc, CR_BEGIN_OPCODE ); +} + +void PACK_APIENTRY crPackEnd( void ) +{ + GET_PACKER_CONTEXT(pc); + unsigned char *data_ptr; + (void) pc; + GET_BUFFERED_POINTER_NO_ARGS( pc ); + WRITE_OPCODE( pc, CR_END_OPCODE ); + pc->buffer.in_BeginEnd = 0; +} + +void PACK_APIENTRY crPackEndSWAP( void ) +{ + GET_PACKER_CONTEXT(pc); + unsigned char *data_ptr; + (void) pc; + GET_BUFFERED_POINTER_NO_ARGS( pc ); + WRITE_OPCODE( pc, CR_END_OPCODE ); + pc->buffer.in_BeginEnd = 0; +} +