Cleanup and Bugfixes
[tpg/acess2.git] / Modules / IPStack / link.c
1 /*
2  * Acess2 IP Stack
3  * - Link/Media Layer Interface
4  */
5 #include "ipstack.h"
6 #include "link.h"
7
8 // === CONSTANTS ===
9 #define MAX_PACKET_SIZE 2048
10
11 // === GLOBALS ===
12  int    giRegisteredTypes = 0;
13 struct {
14         Uint16  Type;
15         tPacketCallback Callback;
16 }       *gaRegisteredTypes;
17
18 // === CODE ===
19 /**
20  * \fn void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
21  * \brief Registers a callback for a specific packet type
22  * 
23  * \todo Make thread safe (place a mutex on the list)
24  */
25 void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
26 {
27          int    i;
28         void    *tmp;
29         for( i = giRegisteredTypes; i -- ; )
30         {
31                 if(gaRegisteredTypes[i].Type == Type) {
32                         Warning("[NET  ] Attempt to register 0x%x twice", Type);
33                         return ;
34                 }
35                 // Ooh! Free slot!
36                 if(gaRegisteredTypes[i].Callback == NULL)       break;
37         }
38         
39         if(i == -1)
40         {
41                 tmp = realloc(gaRegisteredTypes, (giRegisteredTypes+1)*sizeof(*gaRegisteredTypes));
42                 if(!tmp) {
43                         Warning("[NET  ] Out of heap space!");
44                         return ;
45                 }
46                 i = giRegisteredTypes;
47                 giRegisteredTypes ++;
48                 gaRegisteredTypes = tmp;
49         }
50         
51         gaRegisteredTypes[i].Callback = Callback;
52         gaRegisteredTypes[i].Type = Type;
53 }
54
55 /**
56  * \fn void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
57  * \brief Formats and sends a packet on the specified interface
58  */
59 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
60 {
61          int    bufSize = sizeof(tEthernetHeader) + Length;
62         Uint8   buf[bufSize];
63         tEthernetHeader *hdr = (void*)buf;
64         
65         hdr->Dest = To;
66         hdr->Src = Adapter->MacAddr;
67         hdr->Type = htons(Type);
68         
69         memcpy(hdr->Data, Buffer, Length);
70         
71         VFS_Write(Adapter->DeviceFD, bufSize, buf);
72 }
73
74 /**
75  * \fn void Link_WatchDevice(tAdapter *Adapter)
76  * \brief Spawns a worker thread to watch the specified adapter
77  */
78 void Link_WatchDevice(tAdapter *Adapter)
79 {
80          int    tid = Proc_SpawnWorker();       // Create a new worker thread
81         
82         if(tid < 0) {
83                 Warning("[NET  ] Unable to create watcher thread for '%s'", Adapter->Device);
84                 return ;
85         }
86         
87         if(tid > 0) {
88                 Log("[NET  ] Watching '%s' using tid %i", Adapter->Device, tid);
89                 return ;
90         }
91         
92         // Child Thread
93         while(Adapter->DeviceFD != -1)
94         {
95                 Uint8   buf[MAX_PACKET_SIZE];
96                 tEthernetHeader *hdr = (void*)buf;
97                  int    ret, i;
98                 
99                 // Wait for a packet (Read on a network device is blocking)
100                 ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf);
101                 if(ret == -1)   break;
102                 
103                 if(ret <= sizeof(tEthernetHeader)) {
104                         Log("[NET  ] Recieved an undersized packet");
105                         continue;
106                 }
107                 
108                 // Check if there is a registered callback for this packet type
109                 for( i = giRegisteredTypes; i--; )
110                 {
111                         if(gaRegisteredTypes[i].Type == hdr->Type)      continue;
112                 }
113                 // No? Ignore it
114                 if( i == -1 )   continue;
115                 
116                 // Call the callback
117                 gaRegisteredTypes[i].Callback(
118                         Adapter,
119                         hdr->Src,
120                         ret - sizeof(tEthernetHeader),
121                         hdr->Data
122                         );
123         }
124         
125         Log("[NET  ] Watcher terminated (file closed)");
126 }

UCC git Repository :: git.ucc.asn.au