#include "ipx.hpp" #include "jnet.hpp" #include "macs.hpp" #include "dprint.hpp" #include "system.h" #include #include #include #include #include #include #include #include "jmalloc.hpp" #include "doscall.hpp" #include "timing.hpp" #define JC_SEG(x) (((long)x)>>4) #define JC_OFF(x) (((long)x)&0xf) static rminfo rm; class in_socket_dispatcher { ipx_in_socket **ins; long *ports; // ports which the in sockets are supposed to be on } ; int ipx_init() { memset(&rm,0,sizeof(rm)); rm.eax=0x7a00; RM_intr(0x2f,&rm); return (rm.eax&0xff)==0xff; } void ipx_uninit() { ; } void close_ipx_socket(int fd) { memset(&rm,0,sizeof(rm)); rm.ebx=1; rm.edx=(ushort)bstl(fd); RM_intr(0x7a,&rm); } void ipx_idle() { memset(&rm,0,sizeof(rm)); rm.ebx=0xa; RM_intr(0x7a,&rm); } uchar *ipx_get_local_address() // same format as above (be sure to jfree this) { uchar *addr=(uchar *)jmalloc(10,"IPX address"); // normal memory return uchar *low_addr=(uchar *)alloc_low_memory(10); memset(&rm,0,sizeof(rm)); rm.ebx=9; rm.esi=JC_OFF(low_addr); rm.es=JC_SEG(low_addr); RM_intr(0x7a,&rm); memcpy(addr,low_addr,10); free_low_memory(low_addr); return addr; } void ipx_listen(ECBStructure *ecb) { memset(&rm,0,sizeof(rm)); rm.esi=JC_OFF(ecb); rm.es=JC_SEG(ecb); rm.ebx=4; RM_intr(0x7a,&rm); if (rm.eax&0xff) { current_sock_err=SOCK_LISTEN_FAIL; sprintf(last_sock_err,"IPX : listen failed"); } } ipx_out_socket::ipx_out_socket(int port) { remote_socket=-1; // mark not connected memset(&rm,0,sizeof(rm)); rm.ebx=0; // Open socket function rm.eax=0; // close on program exit rm.edx=(ushort)(bstl(port)); RM_intr(0x7a,&rm); if (rm.eax&0xff) { current_sock_err=SOCK_CREATE_FAIL; sprintf(last_sock_err,"Unable to open IPX socket\n"); return ; } local_socket=(ushort)bstl((rm.edx&0xffff)); printf("created socket %x\n",local_socket); pk=(JC_ipx_packet *)alloc_low_memory(sizeof(JC_ipx_packet)*MAX_PACKETS); if (!pk) { printf("unable to allocate low memory for packets\n"); exit(0); } memset(pk,0,sizeof(JC_ipx_packet)*MAX_PACKETS); // setup an outgoing packet structure pk[0].ecb.ECBSocket = (ushort)(bstl(local_socket)); pk[0].ecb.FragmentCount = 1; pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx); pk[0].ecb.fAddress[1] = JC_SEG(&pk[0].ipx); // pk[0].ipx.PacketCheckSum=0xffff; uchar *my_addr=ipx_get_local_address(); memcpy(pk[0].ipx.sNetwork,my_addr,10); pk[0].ipx.sSocket=(ushort)(bstl(local_socket)); jfree(my_addr); for (int i=1;i512 ? 512 : bytes_to_write; memcpy(pk[0].buffer,pk_off,size_to_send); pk[0].time_stamp=local_time; local_time++; pk[0].verify_stamp=0xcdc; pk[0].ipx.PacketLength=(ushort)bstl(sizeof(IPXPacketStructure)+6+size_to_send); ipx_send_packet(&pk[0]); pk_off+=size_to_send; bytes_to_write-=size_to_send; } return 1; } int ipx_out_socket::get(packet &pak) { pak.ro=pak.wo=2; int start=-1; time_marker then; do { for (int i=1;start==-1 && i20) // twenty second timeout return 0; } while (start==-1); // wait until we get the packet we are looking for remote_time++; long data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6; if (data_size<2) // even enough space to read packet size? return 0; ushort size; memcpy(&size,pk[start].buffer,2); data_size-=2; size=lstl(size); pak.rend=size+2; pak.make_bigger(pak.rend); uchar *buf=pak.buf+2; uchar *source=pk[start].buffer+2; int bytes_left=size; do { memcpy(buf,source,data_size); buf+=data_size; bytes_left-=data_size; ipx_listen(&pk[start].ecb); // this packet is done and available for listening again pk[start].ecb.InUseFlag = 0x1d; if (bytes_left) // see if we need to get more packets { time_marker then; do { for (int i=1;start==-1 && i20) // twenty second timeout return 0; } while (start==-1); // wait until we get the packet we are looking for remote_time++; source=pk[start].buffer; data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6; } } while (bytes_left>0); return 1; } ipx_out_socket::~ipx_out_socket() { close_ipx_socket(local_socket); free_low_memory(pk); } ipx_in_socket::ipx_in_socket(int Port) { port=Port; listener=new ipx_out_socket(port); } out_socket *ipx_in_socket::check_for_connect() { int start=-1; ipx_idle(); for (int i=1;ipk[i].ecb.InUseFlag) { printf("found a connection\n"); if (listener->pk[i].verify_stamp==0xcdc) start=i; else { listener->pk[i].ecb.InUseFlag=0x1d; ipx_listen(&listener->pk[i].ecb); // this packet is done and available for listening again printf("bad stamp, getting packets from someone else!\n"); } } } if (start!=-1) { ipx_out_socket *nsock=new ipx_out_socket(0); // create a new socket and dynamicly allocate port listener->pk[0].verify_stamp=0xcdc; listener->pk[0].ipx.PacketLength=sizeof(IPXPacketStructure)+6; listener->pk[0].time_stamp=nsock->local_socket; uchar tmp_addr[10]; memcpy(tmp_addr,listener->pk[0].ipx.dNetwork,10); memcpy(listener->pk[0].ipx.dNetwork, listener->pk[start].ipx.sNetwork,12); // source <- dest memcpy(listener->pk[start].ipx.sNetwork,tmp_addr,10); // dest <- source ipx_listen(&listener->pk[start].ecb); // this packet is done and available for listening again listener->pk[start].ecb.InUseFlag = 0x1d; ipx_send_packet(&listener->pk[0]); // send new port info back to caller return nsock; } return NULL; } ipx_in_socket::~ipx_in_socket() { delete listener; }