static bool SetupStream( Stream *stream, MCB *mcb ) { IOCReply1 *rep = (IOCReply1 *)mcb->Control; Port server = mcb->MsgHdr.Reply; if( (mcb->MsgHdr.ContSize*sizeof(word)) < (sizeof(IOCReply1)-sizeof(word)) ) return false; stream->Type = rep->Type; stream->Flags = Flags_Stream|rep->Flags; if ( server == NullPort ) { FreePort( stream->Server ); stream->Server = rep->Object; } else { if( stream->Server != server ) FreePort(stream->Server); stream->Server = server; stream->Flags |= Flags_Server; /* pipes do not have a server despite returning a port on open */ if( stream->Type == Type_Pipe ) stream->Flags ^= Flags_Server; if( (server & Port_Flags_Remote) != 0 ) stream->Flags |= Flags_Remote; } stream->Access = rep->Access; stream->Reply = mcb->MsgHdr.Dest; if(mcb->MsgHdr.FnRc >= Err_Null ) stream->FnMod = mcb->MsgHdr.FnRc; stream->Timeout = stream->Flags&Flags_Fast?mcb->Timeout:IOCTimeout; strcpy(stream->Name,&mcb->Data[rep->Pathname]); if( (stream->Type == Type_Pseudo) && (stream->Flags & Flags_OpenOnGet) ) ReOpen(stream); return true; }
PUBLIC WORD Refine(Object *object, AccMask mask) { word rc = Err_Null; MCB *mcb ; IOCReply2 *rep; Port reply; #ifdef SYSDEB SysDebug(ioc)("Refine(%O,%A)",object,mask); #endif if( (rc = CheckObject(object,C_Locate)) != Err_Null ) return rc; reply = object->Reply; mcb = NewMsgBuf(0); InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP+FG_Refine|object->FnMod); MarshalCommon(mcb,object,NULL); MarshalWord(mcb,mask); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) goto Done; rep = (IOCReply2 *)mcb->Control; object->Access = rep->Cap; /* copy new capability in */ rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("Refine: %E",rc); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("Refine: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); object->Result2 = rc; return rc; }
PUBLIC WORD SetDate( Object * object, STRING name, DateSet * dates ) { word rc = Err_Null; MCB *mcb ; Port reply; #ifdef SYSDEB SysDebug(ioc)("SetDate(%O,%N)",object,name); #endif if( (rc = CheckObject(object,C_Locate)) != Err_Null ) return rc; reply = object->Reply; mcb = NewMsgBuf(0); InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP+FG_SetDate|object->FnMod); MarshalCommon(mcb,object,name); MarshalDate(mcb,dates->Creation); MarshalDate(mcb,dates->Access); MarshalDate(mcb,dates->Modified); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) goto Done; rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("SetDate: %E",rc); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("SetDate: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); object->Result2 = rc; return rc; }
PUBLIC WORD Link( Object * object, string name, Object * to ) { word rc = Err_Null; MCB *mcb ; Port reply; #ifdef SYSDEB SysDebug(ioc)("Link(%O,%N,%O)",object,name,to); #endif if( (rc = CheckObject(object,C_Locate)) != Err_Null ) return rc; reply = object->Reply; mcb = NewMsgBuf(0); InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP+FG_Link|object->FnMod); MarshalCommon(mcb,object,name); MarshalString(mcb,to->Name); MarshalCap(mcb,&to->Access); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) goto Done; rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("Link: %E",rc); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("Link: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); object->Result2 = rc; return rc; }
PUBLIC WORD ObjectInfo( Object * object, STRING name, byte * info ) { word rc = Err_Null; MCB *mcb ; Port reply; #ifdef SYSDEB SysDebug(ioc)("ObjectInfo(%O,%N,%P)",object,name,info); #endif if( (rc = CheckObject(object,C_Locate)) != Err_Null ) return rc; reply = object->Reply; mcb = NewMsgBuf(0); InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP+FG_ObjectInfo|object->FnMod); MarshalCommon(mcb,object,name); if( (rc = IOCMsg(mcb,info)) < Err_Null ) goto Done; rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("ObjectInfo: %E infosize %d",rc,mcb->MsgHdr.DataSize); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("ObjectInfo: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); object->Result2 = rc; return rc; }
PUBLIC WORD Protect( Object * object, STRING name, Matrix matrix ) { word rc = Err_Null; MCB *mcb ; Port reply; #ifdef SYSDEB SysDebug(ioc)("Protect(%O,%N,%X)",object,name,matrix); #endif if( (rc = CheckObject(object,C_Locate)) != Err_Null ) return rc; reply = object->Reply; mcb = NewMsgBuf(0); InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP+FG_Protect|object->FnMod); MarshalCommon(mcb,object,name); MarshalWord(mcb,matrix); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) goto Done; rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("Protect: %E",rc); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("Protect: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); object->Result2 = rc; return rc; }
PUBLIC INT Sync (IN STRING PathTo) /****************************************************************************** ** ** PURPOSE: ** Locates the file server with <PathTo> and sends a "private" message to the ** server to signal a file system synchronisation request. ** ** PARAMETERS: ** ** In: ** <PathTo> Path to the file server ** ** RETURN: ** SyncOK No error occured ** ** EXAMPLE: ** ** In: ** <PathTo> = "/helios/bin/fs" ** ** Return: ** SyncOK ** *** endspec *******************************************************************/ { MCB Mcb; word E; Port Reply; word ControlV [IOCMsgMax]; byte DataV [IOCDataMax]; /******************************************************************************* ** ** -Get a port for the reply message ** -Basic initialisation of the MessageControlBlock ** *******************************************************************************/ Reply = NewPort (); InitMCB (&Mcb, MsgHdr_Flags_preserve, MyTask->IOCPort, Reply, FC_GSP | SS_HardDisk | FG_Private | FO_ForceSync); /******************************************************************************* ** ** -Preparing control and data vector ** *******************************************************************************/ Mcb.Control = ControlV; Mcb.Data = DataV; MarshalCommon (&Mcb, Null (Object), PathTo); /******************************************************************************* ** ** -Send the message to the server ** -Expect the server's reply (infinite wait) ** -Release the port ** -Normal termination ** *******************************************************************************/ E = PutMsg (&Mcb); InitMCB (&Mcb, MsgHdr_Flags_preserve, Reply, NullPort, 0); Mcb.Timeout = MaxInt; GetMsg (&Mcb); FreePort (Reply); return (SyncOK); }
PUBLIC Stream * Open( Object * object, string name, word mode ) { word rc = Err_Null; Stream *stream = NULL; MCB *mcb; IOCReply1 *rep; word stlen; Port reply; #ifdef SYSDEB SysDebug(ioc)("Open(%O,%N,%x)",object,name,mode); #endif if( CheckObject(object,C_Locate) != Err_Null ) return Null(Stream); reply = NewPort(); mcb = NewMsgBuf(0); rep = (IOCReply1 *)mcb->Control; InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP|FG_Open|object->FnMod); MarshalCommon(mcb,object,name); MarshalWord(mcb,mode); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) goto Done; stlen = sizeof(Stream) + (word)strlen(mcb->Data+rep->Pathname) + SafetyMargin; stream = (Stream *)Malloc(stlen); if( stream == NULL ) { rc = EC_Error|SS_SysLib|EG_NoMemory|EO_Stream; goto Done; } else memclr( (void *)stream, (int)stlen ); if( SetupStream( stream, mcb ) ) { stream->Flags |= mode&Flags_SaveMode; InitSemaphore( &stream->Mutex, 1 ); stream->Pos = 0; } AddStream( stream ); rc = Err_Null; if( mode & Flags_Append ) Seek(stream, S_End, 0); Done: #ifdef SYSDEB SysDebug(ioc)("Open: %E stream: %S",rc,stream); #endif FreeMsgBuf(mcb); if( rc < Err_Null ) FreePort(reply); object->Result2 = rc; return stream; }
PUBLIC Object * Create( Object * object, string name, word type, word size, byte * data ) { word rc = Err_Null; Object *obj = Null(Object); MCB *mcb; IOCReply1 *rep; word oblen; Port reply; #ifdef SYSDEB SysDebug(ioc)("Create(%O,%N,%T,%d,%P)",object,name,type,size,data); #endif if ( CheckObject(object,C_Locate) != Err_Null ) { return NULL; } reply = NewPort(); mcb = NewMsgBuf(0); rep = (IOCReply1 *)mcb->Control; InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP|FG_Create|object->FnMod); MarshalCommon(mcb,object,name); MarshalWord(mcb,type); MarshalWord(mcb,size); MarshalOffset(mcb); MarshalData(mcb,size,data); mcb->Timeout = object->Timeout; /* IOdebug( "Create: sending message" ); */ if ( (rc = IOCMsg(mcb, NULL)) < Err_Null ) { /* IOdebug( "Create: message send failed" ); */ goto Done; } /* IOdebug( "Create: message sent" ); */ oblen = sizeof(Object) + (word)strlen(mcb->Data+rep->Pathname) + SafetyMargin; obj = (Object *)Malloc(oblen); if ( obj == NULL ) { rc = EC_Error|SS_SysLib|EG_NoMemory|EO_Object; goto Done; } else memclr( (void *)obj, (int)oblen ); obj->Type = rep->Type; obj->Flags = rep->Flags; obj->Access = rep->Access; obj->Reply = reply; obj->FnMod = rc & SS_Mask; obj->Timeout = IOCTimeout; strcpy(obj->Name,mcb->Data+rep->Pathname); AddObject( obj ); rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("Create: %E object: %O",rc,obj); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("Create: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); if( rc < Err_Null ) FreePort(reply); object->Result2 = rc; return obj; }
PUBLIC Object * Locate( Object * object, STRING name ) { word rc = Err_Null; Object *obj = Null(Object); MCB *mcb; IOCReply1 *rep; word oblen; Port reply; word fnmod = 0; #ifdef SYSDEB SysDebug(ioc)("Locate(%O,%N)",object,name); #endif /* Locate can be called with a null object pointer */ if( object != NULL ) { if( CheckObject(object,C_Locate) != Err_Null ) { return NULL; } fnmod = object->FnMod; } reply = NewPort(); mcb = NewMsgBuf(0); rep = (IOCReply1 *)mcb->Control; InitMCB(mcb,MsgHdr_Flags_preserve, MyTask->IOCPort,reply,FC_GSP|FG_Locate|fnmod); MarshalCommon(mcb,object,name); if( (rc = IOCMsg(mcb,NULL)) < Err_Null ) { goto Done; } oblen = sizeof(Object) + (word)strlen(mcb->Data+rep->Pathname) + SafetyMargin; obj = (Object *)Malloc(oblen); if( obj == NULL ) { rc = EC_Error|SS_SysLib|EG_NoMemory|EO_Object; goto Done; } else memclr( (void *)obj, (int)oblen ); obj->Type = rep->Type; obj->Flags = rep->Flags; obj->Access = rep->Access; obj->Reply = reply; obj->FnMod = rc & SS_Mask; obj->Timeout = IOCTimeout; strcpy(obj->Name,mcb->Data+rep->Pathname); AddObject( obj ); rc = Err_Null; Done: #ifdef SYSDEB SysDebug(ioc)("Locate: %E object: %O",rc,obj); if( mcb->MsgHdr.Reply != NullPort ) SysDebug(error)("Locate: Non-Null Reply port %x",mcb->MsgHdr.Reply); #endif if( mcb->MsgHdr.Reply != NullPort ) FreePort(mcb->MsgHdr.Reply); FreeMsgBuf(mcb); if( object != Null(Object) ) object->Result2 = rc; if( rc < Err_Null ) FreePort(reply); return obj; }
int main ( int argc, char *argv[] ) { char *tname; char wmname[100]; MCB m; word e; word Control_V[IOCMsgMax]; byte Data_V[IOCDataMax]; Port reply; /* Check args for plausibility */ if ( argc == 1 ) { strncpy ( wmname, Heliosno ( stdin )->Name, 99 ); wmname[99] = '\0'; * ( strrchr ( wmname, c_dirchar ) ) = '\0'; } else { strncpy ( wmname, argv[1], 99 ); wmname[99] = '\0'; if ( argc > 2 ) fprintf (stderr, "%s : Further arguments are ignored !\n", argv[0] ); } /* printf ( "%s: window server is \"%s\".\n", argv[0], wmname ); */ /*----------------- Prepare MCB for marshalling ---------------------*/ reply = NewPort (); /* Basic initialisation of the */ /* MesssageControlBlock */ InitMCB ( &m, MsgHdr_Flags_preserve, MyTask->IOCPort, reply, FC_GSP + FG_Terminate); /* Preparing control and data */ m.Control = Control_V; /* vector */ m.Data = Data_V; MarshalCommon ( &m, Null ( Object ), wmname ); MarshalString ( &m, tname ); /* printf ( "%s sending request.\n", argv[0] ); */ /* fflush ( stdout ); */ e = PutMsg ( &m ); /* Send message to the server */ if ( e != Err_Null ) { fprintf (stderr, "%s : Can't send message to server %s :%x\n", argv[0], wmname, e); return 1; } /* Wait for reply */ /* from the window server... */ InitMCB ( &m, MsgHdr_Flags_preserve, reply, NullPort, 0 ); m.Timeout = MaxInt; /* printf ( "%s waiting for reply.\n", argv[0] ); */ /* fflush ( stdout ); */ e = GetMsg ( &m ); FreePort ( reply ); if ( m.MsgHdr.FnRc == FC_GSP + SS_Window + FG_Terminate ) return 0; else { fprintf (stderr,"%s: Failed to terminate %s - %08x\n", argv[0], wmname, m.MsgHdr.FnRc ); return 1; } }
static void tcpThread(void *context) { Socket *sock = (Socket*) context; TCPSocket *tcpsock = (TCPSocket*) context; Semaphore *sems[4] = {&tcpsock->semConnected, &tcpsock->semStop, &tcpsock->semAck, &tcpsock->semAckOut}; Semaphore *semsOut[3] = {&tcpsock->semStop, &tcpsock->semAckOut, &tcpsock->semSendFetch}; detachMe(); uint16_t srcport, dstport; if (sock->domain == AF_INET) { const struct sockaddr_in *inaddr = (const struct sockaddr_in*) &tcpsock->peername; struct sockaddr_in *inname = (struct sockaddr_in*) &tcpsock->sockname; srcport = inname->sin_port; dstport = inaddr->sin_port; } else { const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6*) &tcpsock->peername; struct sockaddr_in6 *inname = (struct sockaddr_in6*) &tcpsock->sockname; inname->sin6_family = AF_INET6; srcport = inname->sin6_port; dstport = inaddr->sin6_port; }; int connectDone = 0; if (tcpsock->state == TCP_ESTABLISHED) { sems[0] = NULL; connectDone = 1; }; int wantExit = 0; while (1) { if (wantExit) break; uint64_t deadline = getNanotime() + sock->options[GSO_SNDTIMEO]; if (sock->options[GSO_SNDTIMEO] == 0) { deadline = 0; }; int sendOK = 0; int retransCount = 16; while (((getNanotime() < deadline) || (deadline == 0)) && (retransCount--)) { tcpsock->currentOut->segment->ackno = htonl(tcpsock->nextAckNo); ChecksumOutbound(tcpsock->currentOut); int status = sendPacketEx(&tcpsock->sockname, &tcpsock->peername, tcpsock->currentOut->segment, tcpsock->currentOut->size, IPPROTO_TCP, sock->options, sock->ifname); if (status != 0) { tcpsock->sockErr = -status; if (tcpsock->state == TCP_CONNECTING) { semSignal(&tcpsock->semConnected); }; tcpsock->state = TCP_TERMINATED; kfree(tcpsock->currentOut); wantExit = 1; break; }; uint8_t bitmap = 0; if (semPoll(4, sems, &bitmap, 0, TCP_RETRANS_TIMEOUT) == 0) { continue; }; if (bitmap & (1 << 1)) { kfree(tcpsock->currentOut); tcpsock->state = TCP_TERMINATED; wantExit = 1; break; }; if (bitmap & (1 << 2)) { semWait(&tcpsock->semAck); sendOK = 1; break; }; if (bitmap & (1 << 3)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); }; }; if (wantExit) break; int wasFin = tcpsock->currentOut->segment->flags & TCP_FIN; kfree(tcpsock->currentOut); if (!sendOK) { tcpsock->sockErr = ETIMEDOUT; if (tcpsock->state == TCP_CONNECTING) { semSignal(&tcpsock->semConnected); }; tcpsock->state = TCP_TERMINATED; return; }; if (!connectDone) { while ((getNanotime() < deadline) || (deadline == 0)) { uint8_t bitmap = 0; semPoll(3, sems, &bitmap, 0, sock->options[GSO_SNDTIMEO]); if (bitmap & (1 << 1)) { tcpsock->state = TCP_TERMINATED; return; }; if (bitmap & (1 << 0)) { connectDone = 1; break; }; }; if (!connectDone) { tcpsock->sockErr = ETIMEDOUT; semSignal(&tcpsock->semConnected); tcpsock->state = TCP_TERMINATED; return; }; sems[0] = NULL; tcpsock->state = TCP_ESTABLISHED; }; if (wasFin) break; while (1) { uint8_t bitmap = 0; semPoll(3, semsOut, &bitmap, 0, 0); if (bitmap & (1 << 2)) { if (bitmap & (1 << 1)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); }; int count = semWaitGen(&tcpsock->semSendFetch, 512, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, (size_t)count); ob->segment->srcport = srcport; ob->segment->dstport = dstport; ob->segment->seqno = htonl(tcpsock->nextSeqNo); // ackno filled in at the start of the loop iteration ob->segment->dataOffsetNS = 0x50; ob->segment->flags = TCP_PSH | TCP_ACK; // a count of zero means end of data, so send FIN. if (count == 0) { ob->segment->flags = TCP_FIN | TCP_ACK; tcpsock->nextSeqNo++; }; ob->segment->winsz = htons(TCP_BUFFER_SIZE); uint8_t *put = (uint8_t*) &ob->segment[1]; uint32_t size = (uint32_t)count; while (count--) { *put++ = tcpsock->bufSend[tcpsock->idxSendFetch]; tcpsock->idxSendFetch = (tcpsock->idxSendFetch+1) % TCP_BUFFER_SIZE; }; tcpsock->nextSeqNo += size; tcpsock->expectedAck = tcpsock->nextSeqNo; tcpsock->currentOut = ob; semSignal2(&tcpsock->semSendPut, (int)size); break; // continues the outer loop }; if (bitmap & (1 << 1)) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, 0); TCPSegment *ack = ob->segment; ack->srcport = srcport; ack->dstport = dstport; ack->seqno = htonl(tcpsock->nextSeqNo); ack->ackno = htonl(tcpsock->nextAckNo); ack->dataOffsetNS = 0x50; ack->flags = TCP_ACK; ack->winsz = htons(TCP_BUFFER_SIZE); ChecksumOutbound(ob); sendPacketEx(&tcpsock->sockname, &tcpsock->peername, ob->segment, ob->size, IPPROTO_TCP, sock->options, sock->ifname); kfree(ob); }; if (bitmap & (1 << 0)) { tcpsock->state = TCP_TERMINATED; wantExit = 1; break; }; }; }; // wait up to 4 minutes, acknowledging any packets if necessary (during a clean exit) uint64_t deadline = getNanotime() + 4UL * 60UL * 1000000000UL; uint64_t currentTime; Semaphore *semsClosing[2] = {&tcpsock->semStop, &tcpsock->semAckOut}; while ((currentTime = getNanotime()) < deadline) { uint8_t bitmap = 0; semPoll(2, semsClosing, &bitmap, 0, deadline - currentTime); if (bitmap & (1 << 0)) { wantExit = 1; semsClosing[0] = NULL; }; if (bitmap & (1 << 1)) { if (!wantExit) { semWaitGen(&tcpsock->semAckOut, -1, 0, 0); TCPOutbound *ob = CreateOutbound(&tcpsock->sockname, &tcpsock->peername, 0); TCPSegment *ack = ob->segment; ack->srcport = srcport; ack->dstport = dstport; ack->seqno = htonl(tcpsock->nextSeqNo); ack->ackno = htonl(tcpsock->nextAckNo); ack->dataOffsetNS = 0x50; ack->flags = TCP_FIN | TCP_ACK; ack->winsz = htons(TCP_BUFFER_SIZE); ChecksumOutbound(ob); sendPacketEx(&tcpsock->sockname, &tcpsock->peername, ob->segment, ob->size, IPPROTO_TCP, sock->options, sock->ifname); kfree(ob); }; }; }; // wait for the socket to actually be closed by the application (in case it wasn't already) while (semWaitGen(&tcpsock->semSendFetch, 512, 0, 0) != 0); // free the port and socket FreePort(srcport); FreeSocket(sock); };