-// --- Listening Server
-tVFS_Node *UDP_Server_Init(tInterface *Interface)
-{
- tUDPServer *new;
- new = calloc( sizeof(tUDPServer), 1 );
- if(!new) return NULL;
-
- new->Node.ImplPtr = new;
- new->Node.Flags = VFS_FFLAG_DIRECTORY;
- new->Node.NumACLs = 1;
- new->Node.ACLs = &gVFS_ACL_EveryoneRX;
- new->Node.ReadDir = UDP_Server_ReadDir;
- new->Node.FindDir = UDP_Server_FindDir;
- new->Node.IOCtl = UDP_Server_IOCtl;
- new->Node.Close = UDP_Server_Close;
-
- Mutex_Acquire(&glUDP_Servers);
- new->Next = gpUDP_Servers;
- gpUDP_Servers = new;
- Mutex_Release(&glUDP_Servers);
-
- return &new->Node;
-}
-
-/**
- * \brief Wait for a connection and return its ID in a string
- */
-char *UDP_Server_ReadDir(tVFS_Node *Node, int ID)
-{
- tUDPServer *srv = Node->ImplPtr;
- tUDPChannel *chan;
- char *ret;
-
- if( srv->ListenPort == 0 ) return NULL;
-
- // Lock (so another thread can't collide with us here) and wait for a connection
- Mutex_Acquire( &srv->Lock );
- while( srv->NewChannels == NULL ) Threads_Yield();
- // Pop the connection off the new list
- chan = srv->NewChannels;
- srv->NewChannels = chan->Next;
- // Release the lock
- Mutex_Release( &srv->Lock );
-
- // Create the ID string and return it
- ret = malloc(11+1);
- sprintf(ret, "%i", chan->Node.ImplInt);
-
- return ret;
-}
-
-/**
- * \brief Take a string and find the channel
- */
-tVFS_Node *UDP_Server_FindDir(tVFS_Node *Node, const char *Name)
-{
- tUDPServer *srv = Node->ImplPtr;
- tUDPChannel *chan;
- int id = atoi(Name);
-
- for(chan = srv->Channels;
- chan;
- chan = chan->Next)
- {
- if( chan->Node.ImplInt < id ) continue;
- if( chan->Node.ImplInt > id ) break; // Go sorted lists!
-
- return &chan->Node;
- }
-
- return NULL;
-}
-
-/**
- * \brief Names for server IOCtl Calls
- */
-static const char *casIOCtls_Server[] = {
- DRV_IOCTLNAMES,
- "getset_listenport",
- NULL
- };
-/**
- * \brief Channel IOCtls
- */
-int UDP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
- tUDPServer *srv = Node->ImplPtr;
-
- ENTER("pNode iID pData", Node, ID, Data);
- switch(ID)
- {
- BASE_IOCTLS(DRV_TYPE_MISC, "UDP Server", 0x100, casIOCtls_Server);
-
- case 4: // getset_localport (returns bool success)
- if(!Data) LEAVE_RET('i', srv->ListenPort);
- if(!CheckMem( Data, sizeof(Uint16) ) ) {
- LOG("Invalid pointer %p", Data);
- LEAVE_RET('i', -1);
- }
- // Set port
- srv->ListenPort = *(Uint16*)Data;
- // Permissions check (Ports lower than 1024 are root-only)
- if(srv->ListenPort != 0 && srv->ListenPort < 1024) {
- if( Threads_GetUID() != 0 ) {
- LOG("Attempt by non-superuser to listen on port %i", srv->ListenPort);
- srv->ListenPort = 0;
- LEAVE_RET('i', -1);
- }
- }
- // Allocate a random port if requested
- if( srv->ListenPort == 0 )
- srv->ListenPort = UDP_int_AllocatePort();
- else
- {
- // Else, mark the requested port as used
- if( UDP_int_MarkPortAsUsed(srv->ListenPort) == 0 ) {
- LOG("Port %i us currently in use", srv->ListenPort);
- srv->ListenPort = 0;
- LEAVE_RET('i', -1);
- }
- LEAVE_RET('i', 1);
- }
- LEAVE_RET('i', 1);
-
- default:
- LEAVE_RET('i', -1);
- }
- LEAVE_RET('i', 0);
-}
-
-void UDP_Server_Close(tVFS_Node *Node)
-{
- tUDPServer *srv = Node->ImplPtr;
- tUDPServer *prev;
- tUDPChannel *chan;
- tUDPPacket *tmp;
-
-
- // Remove from the main list first
- Mutex_Acquire(&glUDP_Servers);
- if(gpUDP_Servers == srv)
- gpUDP_Servers = gpUDP_Servers->Next;
- else
- {
- for(prev = gpUDP_Servers;
- prev->Next && prev->Next != srv;
- prev = prev->Next);
- if(!prev->Next)
- Warning("[UDP ] Bookeeping Fail, server %p is not in main list", srv);
- else
- prev->Next = prev->Next->Next;
- }
- Mutex_Release(&glUDP_Servers);
-
-
- Mutex_Acquire(&srv->Lock);
- for(chan = srv->Channels;
- chan;
- chan = chan->Next)
- {
- // Clear Queue
- SHORTLOCK(&chan->lQueue);
- while(chan->Queue)
- {
- tmp = chan->Queue;
- chan->Queue = tmp->Next;
- free(tmp);
- }
- SHORTREL(&chan->lQueue);
-
- // Free channel structure
- free(chan);
- }
- Mutex_Release(&srv->Lock);
-
- free(srv);
-}
-