sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
ps2ips.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
15
16/*
17
18NOTES:
19
20- recv/recvfrom/send/sendto are designed so that the data buffer can be misaligned, and the recv/send size is
21 not restricted to a multiple of 64 bytes. The implimentation method was borrowed from fileio
22 read/write code :P
23
24*/
25
26#include <types.h>
27#include <loadcore.h>
28#include <stdio.h>
29#include <sifman.h>
30#include <sifcmd.h>
31#include <sysclib.h>
32#include <thbase.h>
33#include <intrman.h>
34#include <ps2ip.h>
35#include <ps2ip_rpc.h>
36
37#define MODNAME "TCP/IP_Stack_RPC"
38IRX_ID(MODNAME, 1, 1);
39
40#define BUFF_SIZE (1024)
41
42#define MIN(a, b) (((a)<(b))?(a):(b))
43#define RDOWN_64(a) (((a) >> 6) << 6)
44
45static SifRpcDataQueue_t ps2ips_queue;
46static SifRpcServerData_t ps2ips_server;
47static u8 _rpc_buffer[512 * 4] __attribute__((__aligned__(4)));
48
49static char lwip_buffer[BUFF_SIZE + 32];
50static rests_pkt rests;
51
52static void do_accept( void * rpcBuffer, int size )
53{
54 int *ptr = rpcBuffer;
55 cmd_pkt *pkt = (cmd_pkt *)ptr;
56 struct sockaddr addr;
57 int addrlen, ret;
58
59 (void)size;
60
61 ret = accept(pkt->socket, &addr, &addrlen);
62
63 pkt->socket = ret;
64 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
65 pkt->len = sizeof(struct sockaddr);
66}
67
68static void do_bind( void * rpcBuffer, int size )
69{
70 int *ptr = rpcBuffer;
71 cmd_pkt *pkt = (cmd_pkt *)rpcBuffer;
72 int ret;
73
74 (void)size;
75
76 ret = bind(pkt->socket, &pkt->sockaddr, pkt->len);
77
78 ptr[0] = ret;
79}
80
81static void do_disconnect( void * rpcBuffer, int size )
82{
83 int *ptr = rpcBuffer;
84 int ret;
85
86 (void)size;
87
88 ret = disconnect(ptr[0]);
89
90 ptr[0] = ret;
91}
92
93static void do_connect( void * rpcBuffer, int size )
94{
95 int *ptr = rpcBuffer;
96 cmd_pkt *pkt = (cmd_pkt *)_rpc_buffer;
97 int ret;
98
99 (void)size;
100
101 ret = connect(pkt->socket, &pkt->sockaddr, pkt->len);
102
103 ptr[0] = ret;
104}
105
106static void do_listen( void * rpcBuffer, int size )
107{
108 int *ptr = rpcBuffer;
109 int ret;
110
111 (void)size;
112
113 ret = listen(ptr[0], ptr[1]);
114
115 ptr[0] = ret;
116}
117
118static void do_recv( void * rpcBuffer, int size )
119{
120 int srest, erest, asize; // size of unaligned portion, remainder portion, aligned portion
121 void *abuffer, *aebuffer; // aligned buffer start, aligned buffer end
122 int s_offset; // offset into lwip_buffer of srest data
123 int rlen, recvlen;
124 int dma_id = 0;
125 int intr_stat;
126 s_recv_pkt *recv_pkt = (s_recv_pkt *)rpcBuffer;
127 r_recv_pkt *ret_pkt = (r_recv_pkt *)rpcBuffer;
128 struct t_SifDmaTransfer sifdma;
129
130 (void)size;
131
132 if(recv_pkt->length <= 64)
133 {
134 srest = recv_pkt->length;
135
136 } else {
137
138 if( ((int)recv_pkt->ee_addr & 0x3F) == 0 ) // ee address is aligned
139 srest = 0;
140 else
141 srest = RDOWN_64((int)recv_pkt->ee_addr) - (int)recv_pkt->ee_addr + 64;
142 }
143
144 s_offset = 64 - srest;
145 recvlen = MIN(BUFF_SIZE, recv_pkt->length);
146
147 // Do actual TCP recv
148 rlen = recv(recv_pkt->socket, lwip_buffer + s_offset, recvlen, recv_pkt->flags);
149
150 if(rlen <= 0) goto recv_end;
151 if(rlen <= 64) srest = rlen;
152
153 // fill sbuffer, calculate align buffer & erest valules, fill ebuffer
154 if(srest)
155 memcpy((void *)rests.sbuffer, (void *)(lwip_buffer + s_offset), srest);
156
157 if(rlen > 64)
158 {
159 abuffer = recv_pkt->ee_addr + srest; // aligned buffer (round up)
160 aebuffer = (void *)RDOWN_64((int)recv_pkt->ee_addr + rlen); // aligned buffer end (round down)
161
162 asize = (int)aebuffer - (int)abuffer;
163
164 erest = recv_pkt->ee_addr + rlen - aebuffer;
165
166 if(erest)
167 memcpy((void *)rests.ebuffer, (void *)(lwip_buffer + 64 + asize), erest);
168
169// printf("srest = 0x%X\nabuffer = 0x%X\naebuffer = 0x%X\nasize = 0x%X\nerest = 0x%X\n", srest, abuffer, aebuffer, asize, erest);
170
171 } else {
172
173 abuffer = aebuffer = NULL;
174 erest = asize = 0;
175
176 }
177
178 // DMA back the abuffer
179 if(asize)
180 {
181 while(sceSifDmaStat(dma_id) >= 0);
182
183 sifdma.src = lwip_buffer + 64;
184 sifdma.dest = abuffer;
185 sifdma.size = asize;
186 sifdma.attr = 0;
187 CpuSuspendIntr(&intr_stat);
188 dma_id = sceSifSetDma(&sifdma, 1);
189 CpuResumeIntr(intr_stat);
190 }
191
192 // Fill rest of rests structure, dma back
193 rests.ssize = srest;
194 rests.esize = erest;
195 rests.sbuf = recv_pkt->ee_addr;
196 rests.ebuf = aebuffer;
197
198 while(sceSifDmaStat(dma_id) >= 0);
199
200 sifdma.src = &rests;
201 sifdma.dest = recv_pkt->intr_data;
202 sifdma.size = sizeof(rests_pkt);
203 sifdma.attr = 0;
204 CpuSuspendIntr(&intr_stat);
205 dma_id = sceSifSetDma(&sifdma, 1);
206 CpuResumeIntr(intr_stat);
207
208recv_end:
209 ret_pkt->ret = rlen;
210}
211
212static void do_recvfrom( void * rpcBuffer, int size )
213{
214 int srest, erest, asize; // size of unaligned portion, remainder portion, aligned portion
215 void *abuffer, *aebuffer; // aligned buffer start, aligned buffer end
216 int s_offset; // offset into lwip_buffer of srest data
217 int rlen, recvlen;
218 int dma_id = 0;
219 int intr_stat;
220 s_recv_pkt *recv_pkt = (s_recv_pkt *)rpcBuffer;
221 r_recv_pkt *ret_pkt = (r_recv_pkt *)rpcBuffer;
222 static struct t_SifDmaTransfer sifdma;
223 static struct sockaddr sockaddr;
224 int fromlen;
225
226 (void)size;
227
228 if(recv_pkt->length <= 64)
229 {
230 srest = recv_pkt->length;
231
232 } else {
233
234 if( ((int)recv_pkt->ee_addr & 0x3F) == 0 ) // ee address is aligned
235 srest = 0;
236 else
237 srest = RDOWN_64((int)recv_pkt->ee_addr) - (int)recv_pkt->ee_addr + 64;
238 }
239
240 s_offset = 64 - srest;
241 recvlen = MIN(BUFF_SIZE, recv_pkt->length);
242
243 // Do actual UDP recvfrom
244 rlen = recvfrom(recv_pkt->socket, lwip_buffer + s_offset, recvlen, recv_pkt->flags, &sockaddr, &fromlen);
245
246 if(rlen <= 0) goto recv_end;
247 if(rlen <= 64) srest = rlen;
248
249 // copy sockaddr struct to return packet
250 memcpy((void *)&ret_pkt->sockaddr, (void *)&sockaddr, sizeof(struct sockaddr));
251
252 // fill sbuffer, calculate align buffer & erest valules, fill ebuffer
253 if(srest)
254 memcpy((void *)rests.sbuffer, (void *)(lwip_buffer + s_offset), srest);
255
256 if(rlen > 64)
257 {
258 abuffer = recv_pkt->ee_addr + srest; // aligned buffer (round up)
259 aebuffer = (void *)RDOWN_64((int)recv_pkt->ee_addr + rlen); // aligned buffer end (round down)
260
261 asize = (int)aebuffer - (int)abuffer;
262
263 erest = recv_pkt->ee_addr + rlen - aebuffer;
264
265 if(erest)
266 memcpy((void *)rests.ebuffer, (void *)(lwip_buffer + 64 + asize), erest);
267
268// printf("srest = 0x%X\nabuffer = 0x%X\naebuffer = 0x%X\nasize = 0x%X\nerest = 0x%X\n", srest, abuffer, aebuffer, asize, erest);
269
270 } else {
271
272 abuffer = aebuffer = NULL;
273 erest = asize = 0;
274
275 }
276
277 // DMA back the abuffer
278 if(asize)
279 {
280 while(sceSifDmaStat(dma_id) >= 0);
281
282 sifdma.src = lwip_buffer + 64;
283 sifdma.dest = abuffer;
284 sifdma.size = asize;
285 sifdma.attr = 0;
286 CpuSuspendIntr(&intr_stat);
287 dma_id = sceSifSetDma(&sifdma, 1);
288 CpuResumeIntr(intr_stat);
289 }
290
291 // Fill rest of rests structure, dma back
292 rests.ssize = srest;
293 rests.esize = erest;
294 rests.sbuf = recv_pkt->ee_addr;
295 rests.ebuf = aebuffer;
296
297 while(sceSifDmaStat(dma_id) >= 0);
298
299 sifdma.src = &rests;
300 sifdma.dest = recv_pkt->intr_data;
301 sifdma.size = sizeof(rests_pkt);
302 sifdma.attr = 0;
303 CpuSuspendIntr(&intr_stat);
304 dma_id = sceSifSetDma(&sifdma, 1);
305 CpuResumeIntr(intr_stat);
306
307recv_end:
308 ret_pkt->ret = rlen;
309}
310
311static void do_send( void * rpcBuffer, int size )
312{
313 int *ptr = rpcBuffer;
314 send_pkt *pkt = (send_pkt *)rpcBuffer;
315 int slen, sendlen;
316 int s_offset; // offset into lwip_buffer for malign data
317 void *ee_pos;
318 SifRpcReceiveData_t rdata;
319
320 (void)size;
321
322 if(pkt->malign)
323 {
324// printf("send: misaligned = %d\n", pkt->malign);
325
326 s_offset = 64 - pkt->malign;
327 memcpy((void *)(lwip_buffer + s_offset), pkt->malign_buff, pkt->malign);
328
329 } else s_offset = 64;
330
331 ee_pos = pkt->ee_addr + pkt->malign;
332
333 sendlen = MIN(BUFF_SIZE, pkt->length);
334
335 sceSifGetOtherData(&rdata, ee_pos, lwip_buffer + 64, sendlen - pkt->malign, 0);
336
337 // So actual TCP send
338 slen = send(pkt->socket, lwip_buffer + s_offset, sendlen, pkt->flags);
339
340 ptr[0] = slen;
341}
342
343
344static void do_sendto( void * rpcBuffer, int size )
345{
346 int *ptr = rpcBuffer;
347 send_pkt *pkt = (send_pkt *)rpcBuffer;
348 int slen, sendlen;
349 int s_offset; // offset into lwip_buffer for malign data
350 void *ee_pos;
351 SifRpcReceiveData_t rdata;
352
353 (void)size;
354
355 if(pkt->malign)
356 {
357// printf("send: misaligned = %d\n", pkt->malign);
358
359 s_offset = 64 - pkt->malign;
360 memcpy((void *)(lwip_buffer + s_offset), pkt->malign_buff, pkt->malign);
361
362 } else s_offset = 64;
363
364 ee_pos = pkt->ee_addr + pkt->malign;
365
366 sendlen = MIN(BUFF_SIZE, pkt->length);
367
368 sceSifGetOtherData(&rdata, ee_pos, lwip_buffer + 64, sendlen - pkt->malign, 0);
369
370 // So actual UDP sendto
371 slen = sendto(pkt->socket, lwip_buffer + s_offset, sendlen, pkt->flags, &pkt->sockaddr, sizeof(struct sockaddr));
372
373 ptr[0] = slen;
374}
375
376static void do_socket( void * rpcBuffer, int size )
377{
378 int *ptr = rpcBuffer;
379 int ret;
380
381 (void)size;
382
383 ret = socket(ptr[0], ptr[1], ptr[2]);
384
385 ptr[0] = ret;
386}
387
388static void do_getconfig(void *rpcBuffer, int size)
389{
390 (void)size;
391
392 ps2ip_getconfig((char *)rpcBuffer, (t_ip_info *)rpcBuffer);
393}
394
395static void do_setconfig(void *rpcBuffer, int size)
396{
397 (void)size;
398
399 ps2ip_setconfig((t_ip_info *)rpcBuffer);
400}
401
402static void do_select( void * rpcBuffer, int size )
403{
404 select_pkt *pkt = (select_pkt*)_rpc_buffer;
405 struct timeval tv;
406 int result;
407
408 (void)rpcBuffer;
409 (void)size;
410
411 /* Reconstruct an IOP-native struct timeval from the wire fields. */
412 if (pkt->timeout_p != NULL)
413 {
414 tv.tv_sec = pkt->timeout_sec;
415 tv.tv_usec = pkt->timeout_usec;
416 }
417
418 /* ps2ip_rpc_fd_set is { unsigned char fd_bits[(MEMP_NUM_NETCONN+7)/8] },
419 * which is byte-identical to lwIP's struct fd_set. The cast is safe and
420 * keeps lwip_select free to mutate the bits in place. */
421 result = select( pkt->maxfdp1,
422 pkt->readset_p != NULL ? (struct fd_set *)&pkt->readset : NULL,
423 pkt->writeset_p != NULL ? (struct fd_set *)&pkt->writeset : NULL,
424 pkt->exceptset_p != NULL ? (struct fd_set *)&pkt->exceptset : NULL,
425 pkt->timeout_p != NULL ? &tv : NULL );
426
427 if (pkt->timeout_p != NULL)
428 {
429 pkt->timeout_sec = (s32)tv.tv_sec;
430 pkt->timeout_usec = (s32)tv.tv_usec;
431 }
432 pkt->result = result;
433}
434
435static void do_ioctlsocket( void *rpcBuffer, int size )
436{
437 ioctl_pkt *pkt = (ioctl_pkt*)_rpc_buffer;
438
439 (void)rpcBuffer;
440 (void)size;
441
442 pkt->result = ioctlsocket( pkt->s,
443 pkt->cmd,
444 pkt->argp != NULL ? &pkt->value : NULL );
445}
446static void do_getsockname( void *rpcBuffer, int size )
447{
448 int *ptr = rpcBuffer;
449 cmd_pkt *pkt = (cmd_pkt *)ptr;
450 struct sockaddr addr;
451 int addrlen, ret;
452
453 (void)size;
454
455 ret = getsockname(pkt->socket, &addr, &addrlen);
456
457 pkt->socket = ret;
458 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
459 pkt->len = sizeof(struct sockaddr);
460}
461
462static void do_getpeername( void *rpcBuffer, int size )
463{
464 int *ptr = rpcBuffer;
465 cmd_pkt *pkt = (cmd_pkt *)ptr;
466 struct sockaddr addr;
467 int addrlen, ret;
468
469 (void)size;
470
471 ret = getpeername(pkt->socket, &addr, &addrlen);
472
473 pkt->socket = ret;
474 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
475 pkt->len = sizeof(struct sockaddr);
476}
477
478static void do_getsockopt( void *rpcBuffer, int size )
479{
480 int ret, s, level, optname, optlen;
481 unsigned char optval[128];
482
483 (void)size;
484
485 s = ((getsockopt_pkt*)rpcBuffer)->s;
486 level = ((getsockopt_pkt*)rpcBuffer)->level;
487 optname = ((getsockopt_pkt*)rpcBuffer)->optname;
488 optlen = sizeof(optval);
489
490 ret = getsockopt(s, level, optname, optval, &optlen);
491
492 ((getsockopt_res_pkt*)rpcBuffer)->result = ret;
493 ((getsockopt_res_pkt*)rpcBuffer)->optlen = optlen;
494 memcpy( ((getsockopt_res_pkt*)rpcBuffer)->buffer, optval, 128 );
495}
496
497static void do_setsockopt( void *rpcBuffer, int size )
498{
499 int *ptr = rpcBuffer, ret;
500 int s;
501 int level;
502 int optname;
503 int optlen;
504 unsigned char optval[128];
505
506 (void)size;
507
508 s = ((setsockopt_pkt*)rpcBuffer)->s;
509 level = ((setsockopt_pkt*)rpcBuffer)->level;
510 optname = ((setsockopt_pkt*)rpcBuffer)->optname;
511 optlen = ((setsockopt_pkt*)rpcBuffer)->optlen;
512 memcpy(optval, ((setsockopt_pkt*)rpcBuffer)->buffer, optlen);
513
514 ret = setsockopt(s, level, optname, optval, optlen);
515 ptr[0] = ret;
516}
517
518#ifdef PS2IP_DNS
519static void do_gethostbyname( void *rpcBuffer, int size )
520{
521 struct hostent *ret;
522 gethostbyname_res_pkt *resPtr = rpcBuffer;
523
524 (void)size;
525
526 if((ret = gethostbyname((char*)_rpc_buffer)) != NULL)
527 {
528 resPtr->result = 0;
529 resPtr->hostent.h_addrtype = ret->h_addrtype;
530 resPtr->hostent.h_length = ret->h_length;
531 memcpy(&resPtr->hostent.h_addr, &ret->h_addr_list[0], sizeof(resPtr->hostent.h_addr));
532 }else{
533 resPtr->result = -1;
534 }
535}
536
537static void do_dns_setserver( void *rpcBuffer, int size )
538{
539 (void)rpcBuffer;
540 (void)size;
541
542 dns_setserver(((dns_setserver_pkt*)_rpc_buffer)->numdns, &((dns_setserver_pkt*)_rpc_buffer)->dnsserver);
543}
544
545static void do_dns_getserver( void *rpcBuffer, int size )
546{
547 const ip_addr_t *dns;
548
549 (void)size;
550
551 dns = dns_getserver(*(u8*)_rpc_buffer);
552 ip_addr_copy(((dns_getserver_res_pkt*)rpcBuffer)->dnsserver, *dns);
553}
554#endif
555
556static void * rpcHandlerFunction(unsigned int command, void * rpcBuffer, int size)
557{
558 switch(command)
559 {
560 case PS2IPS_ID_ACCEPT:
561 do_accept(rpcBuffer, size);
562 break;
563 case PS2IPS_ID_BIND:
564 do_bind(rpcBuffer, size);
565 break;
566 case PS2IPS_ID_DISCONNECT:
567 do_disconnect(rpcBuffer, size);
568 break;
569 case PS2IPS_ID_CONNECT:
570 do_connect(rpcBuffer, size);
571 break;
572 case PS2IPS_ID_LISTEN:
573 do_listen(rpcBuffer, size);
574 break;
575 case PS2IPS_ID_RECV:
576 do_recv(rpcBuffer, size);
577 break;
578 case PS2IPS_ID_RECVFROM:
579 do_recvfrom(rpcBuffer, size);
580 break;
581 case PS2IPS_ID_SEND:
582 do_send(rpcBuffer, size);
583 break;
584 case PS2IPS_ID_SENDTO:
585 do_sendto(rpcBuffer, size);
586 break;
587 case PS2IPS_ID_SOCKET:
588 do_socket(rpcBuffer, size);
589 break;
590 case PS2IPS_ID_GETCONFIG:
591 do_getconfig(rpcBuffer, size);
592 break;
593 case PS2IPS_ID_SETCONFIG:
594 do_setconfig(rpcBuffer, size);
595 break;
596 case PS2IPS_ID_SELECT:
597 do_select(rpcBuffer, size);
598 break;
599 case PS2IPS_ID_IOCTL:
600 do_ioctlsocket(rpcBuffer, size);
601 break;
602 case PS2IPS_ID_GETSOCKNAME:
603 do_getsockname(rpcBuffer, size);
604 break;
605 case PS2IPS_ID_GETPEERNAME:
606 do_getpeername(rpcBuffer, size);
607 break;
608 case PS2IPS_ID_GETSOCKOPT:
609 do_getsockopt(rpcBuffer, size);
610 break;
611 case PS2IPS_ID_SETSOCKOPT:
612 do_setsockopt(rpcBuffer, size);
613 break;
614#ifdef PS2IP_DNS
615 case PS2IPS_ID_GETHOSTBYNAME:
616 do_gethostbyname(rpcBuffer, size);
617 break;
618 case PS2IPS_ID_DNS_SETSERVER:
619 do_dns_setserver(rpcBuffer, size);
620 break;
621 case PS2IPS_ID_DNS_GETSERVER:
622 do_dns_getserver(rpcBuffer, size);
623 break;
624#endif
625 default:
626 printf("PS2IPS: Unknown Function called!\n");
627
628 }
629
630 return rpcBuffer;
631}
632
633static void threadRpcFunction(void *arg)
634{
635 (void)arg;
636
637 printf("PS2IPS: RPC Thread Started\n");
638
639 sceSifSetRpcQueue( &ps2ips_queue , GetThreadId() );
640 sceSifRegisterRpc( &ps2ips_server, PS2IP_IRX, (void *)rpcHandlerFunction,(u8 *)&_rpc_buffer,NULL,NULL, &ps2ips_queue );
641 sceSifRpcLoop( &ps2ips_queue );
642}
643
644int _start( int argc, char *argv[])
645{
646 int threadId;
647 iop_thread_t t;
648
649 (void)argc;
650 (void)argv;
651
652 printf( "PS2IPS: Module Loaded.\n" );
653
654 t.attr = TH_C;
655 t.option = 0;
656 t.thread = &threadRpcFunction;
657 t.stacksize = 0x800;
658 t.priority = 0x1e;
659
660 threadId = CreateThread( &t );
661 if ( threadId < 0 )
662 {
663 printf( "PS2IPS: CreateThread failed. %i\n", threadId );
664 return MODULE_NO_RESIDENT_END;
665 }
666 else
667 {
668 StartThread( threadId, NULL );
669 return MODULE_RESIDENT_END;
670 }
671}
int CpuResumeIntr(int state)
Definition intrman.c:217
int CpuSuspendIntr(int *state)
Definition intrman.c:195
u8 malign_buff[64]
Definition ps2ip_rpc.h:123
Definition time.h:30