Subversion Repositories Kolibri OS

Rev

Rev 3648 | Rev 3658 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
$Revision: 3514 $
19
 
20
 
21
struct  SOCKET
22
 
23
        NextPtr                 dd ? ; pointer to next socket in list
24
        PrevPtr                 dd ? ; pointer to previous socket in list
25
        Number                  dd ? ; socket number
26
 
27
        mutex                   MUTEX
28
 
29
        PID                     dd ? ; process ID
30
        TID                     dd ? ; thread ID
31
        Domain                  dd ? ; INET/LOCAL/..
32
        Type                    dd ? ; RAW/STREAM/DGRAP
33
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
34
        errorcode               dd ?
35
        device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
36
 
37
        options                 dd ?
38
        state                   dd ?
39
        backlog                 dw ? ; how many incoming connections that can be queued
40
 
41
        snd_proc                dd ?
42
        rcv_proc                dd ?
43
 
44
ends
45
 
46
struct  IP_SOCKET               SOCKET
47
 
48
        LocalIP                 rd 4 ; network byte order
49
        RemoteIP                rd 4 ; network byte order
50
 
51
ends
52
 
53
struct  TCP_SOCKET              IP_SOCKET
54
 
55
        LocalPort               dw ? ; network byte order
56
        RemotePort              dw ? ; network byte order
57
 
58
        t_state                 dd ? ; TCB state
59
        t_rxtshift              db ?
60
                                rb 3 ; align
61
        t_rxtcur                dd ?
62
        t_dupacks               dd ?
63
        t_maxseg                dd ?
64
        t_force                 dd ?
65
        t_flags                 dd ?
66
 
67
;---------------
68
; RFC783 page 21
69
 
70
; send sequence
71
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
72
        SND_NXT                 dd ? ; next send sequence number to use
73
        SND_UP                  dd ? ; urgent pointer
74
        SND_WL1                 dd ? ; window minus one
75
        SND_WL2                 dd ? ;
76
        ISS                     dd ? ; initial send sequence number
77
        SND_WND                 dd ? ; send window
78
 
79
; receive sequence
80
        RCV_WND                 dd ? ; receive window
81
        RCV_NXT                 dd ? ; next receive sequence number to use
82
        RCV_UP                  dd ? ; urgent pointer
83
        IRS                     dd ? ; initial receive sequence number
84
 
85
;---------------------
86
; Additional variables
87
 
88
; receive variables
89
        RCV_ADV                 dd ?
90
 
91
; retransmit variables
92
        SND_MAX                 dd ?
93
 
94
; congestion control
95
        SND_CWND                dd ?
96
        SND_SSTHRESH            dd ?
97
 
98
;----------------------
99
; Transmit timing stuff
100
        t_idle                  dd ?
101
        t_rtt                   dd ?
102
        t_rtseq                 dd ?
103
        t_srtt                  dd ?
104
        t_rttvar                dd ?
105
        t_rttmin                dd ?
106
        max_sndwnd              dd ?
107
 
108
;-----------------
109
; Out-of-band data
110
        t_oobflags              dd ?
111
        t_iobc                  dd ?
112
        t_softerror             dd ?
113
 
114
 
115
;---------
116
; RFC 1323                              ; the order of next 4 elements may not change
117
 
118
        SND_SCALE               db ?
119
        RCV_SCALE               db ?
120
        requested_s_scale       db ?
121
        request_r_scale         db ?
122
 
123
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
124
        ts_recent_age           dd ?
125
        last_ack_sent           dd ?
126
 
127
 
128
;-------
129
; Timers
3600 hidnplayr 130
        timer_flags             dd ?
3545 hidnplayr 131
        timer_retransmission    dd ? ; rexmt
132
        timer_persist           dd ?
133
        timer_keepalive         dd ? ; keepalive/syn timeout
134
        timer_timed_wait        dd ? ; also used as 2msl timer
135
 
136
; extra
137
 
138
        ts_ecr                  dd ? ; timestamp echo reply
139
        ts_val                  dd ?
140
 
141
        seg_next                dd ? ; re-assembly queue
142
 
143
        temp_bits               db ?
144
                                rb 3 ; align
145
 
146
ends
147
 
148
struct  UDP_SOCKET              IP_SOCKET
149
 
150
        LocalPort               dw ? ; network byte order
151
        RemotePort              dw ? ; network byte order
152
        firstpacket             db ?
153
 
154
ends
155
 
156
 
157
struct  ICMP_SOCKET             IP_SOCKET
158
 
159
        Identifier              dw ?
160
 
161
ends
162
 
163
 
164
struct  RING_BUFFER
165
 
166
        mutex                   MUTEX
167
        start_ptr               dd ? ; Pointer to start of buffer
168
        end_ptr                 dd ? ; pointer to end of buffer
169
        read_ptr                dd ? ; Read pointer
170
        write_ptr               dd ? ; Write pointer
171
        size                    dd ? ; Number of bytes buffered
172
 
173
ends
174
 
175
struct  STREAM_SOCKET           TCP_SOCKET
176
 
177
        rcv                     RING_BUFFER
178
        snd                     RING_BUFFER
179
 
180
ends
181
 
182
struct  socket_queue_entry
183
 
184
        data_ptr                dd ?
185
        buf_ptr                 dd ?
186
        data_size               dd ?
187
 
188
ends
189
 
190
 
191
SOCKETBUFFSIZE          = 4096     ; in bytes
192
 
193
SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
194
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
195
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
196
 
197
uglobal
198
        net_sockets     rd 4
199
        last_socket_num dd ?
200
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
201
        last_TCP_port   dw ? ;
3647 hidnplayr 202
        socket_mutex    MUTEX
3545 hidnplayr 203
endg
204
 
205
 
206
;-----------------------------------------------------------------
207
;
208
; SOCKET_init
209
;
210
;-----------------------------------------------------------------
211
macro   SOCKET_init {
212
 
213
        xor     eax, eax
214
        mov     edi, net_sockets
215
        mov     ecx, 5
216
        rep     stosd
217
 
218
       @@:
219
        pseudo_random eax
3600 hidnplayr 220
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 221
        jb      @r
3600 hidnplayr 222
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 223
        ja      @r
224
        xchg    al, ah
225
        mov     [last_UDP_port], ax
226
 
227
       @@:
228
        pseudo_random eax
3600 hidnplayr 229
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 230
        jb      @r
3600 hidnplayr 231
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 232
        ja      @r
233
        xchg    al, ah
234
        mov     [last_TCP_port], ax
235
 
3647 hidnplayr 236
        mov     ecx, socket_mutex
237
        call    mutex_init
238
 
3545 hidnplayr 239
}
240
 
241
;-----------------------------------------------------------------
242
;
243
; Socket API (function 74)
244
;
245
;-----------------------------------------------------------------
246
align 4
247
sys_socket:
248
 
249
        cmp     ebx, 255
250
        jz      SOCKET_debug
251
 
252
        cmp     ebx, .number
253
        ja      s_error
254
        jmp     dword [.table + 4*ebx]
255
 
256
  .table:
257
        dd      SOCKET_open     ; 0
258
        dd      SOCKET_close    ; 1
259
        dd      SOCKET_bind     ; 2
260
        dd      SOCKET_listen   ; 3
261
        dd      SOCKET_connect  ; 4
262
        dd      SOCKET_accept   ; 5
263
        dd      SOCKET_send     ; 6
264
        dd      SOCKET_receive  ; 7
265
        dd      SOCKET_set_opt  ; 8
266
        dd      SOCKET_get_opt  ; 9
267
        dd      SOCKET_pair     ; 10
268
  .number = ($ - .table) / 4 - 1
269
 
270
s_error:
3556 hidnplayr 271
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET: error\n"
3545 hidnplayr 272
        mov     dword [esp+32], -1
273
 
274
        ret
275
 
276
;-----------------------------------------------------------------
277
;
278
; SOCKET_open
279
;
280
;  IN:  domain in ecx
281
;       type in edx
282
;       protocol in esi
283
;  OUT: eax is socket num, -1 on error
284
;
285
;-----------------------------------------------------------------
286
align 4
287
SOCKET_open:
288
 
3556 hidnplayr 289
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3545 hidnplayr 290
 
291
        push    ecx edx esi
292
        call    SOCKET_alloc
293
        pop     esi edx ecx
294
        jz      s_error
295
 
296
        mov     [esp+32], edi                   ; return socketnumber
3556 hidnplayr 297
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3545 hidnplayr 298
 
299
;        push    edx
300
;        and     edx, SO_NONBLOCK
301
        or      [eax + SOCKET.options], SO_NONBLOCK ;edx
302
;        pop     edx
303
;        and     edx, not SO_NONBLOCK
304
 
305
        mov     [eax + SOCKET.Domain], ecx
306
        mov     [eax + SOCKET.Type], edx
307
        mov     [eax + SOCKET.Protocol], esi
308
 
309
        cmp     ecx, AF_INET4
310
        jne     .no_inet4
311
 
312
        cmp     edx, SOCK_DGRAM
313
        je      .udp
314
 
315
        cmp     edx, SOCK_STREAM
316
        je      .tcp
317
 
318
        cmp     edx, SOCK_RAW
319
        je      .raw
320
 
321
  .no_inet4:
322
        cmp     ecx, AF_PPP
323
        jne     .no_ppp
324
 
325
        cmp     esi, PPP_PROTO_ETHERNET
326
        je      .pppoe
327
 
328
  .no_ppp:
3556 hidnplayr 329
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n"
3545 hidnplayr 330
        ret
331
 
332
align 4
333
  .raw:
334
        test    esi, esi       ; IP_PROTO_IP
335
        jz      .ip
336
 
337
        cmp     esi, IP_PROTO_ICMP
338
        je      .icmp
339
 
340
        cmp     esi, IP_PROTO_UDP
341
        je      .udp
342
 
343
        cmp     esi, IP_PROTO_TCP
344
        je      .tcp
345
 
346
        ret
347
 
348
align 4
349
  .udp:
350
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
351
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
352
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
353
        ret
354
 
355
align 4
356
  .tcp:
357
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
358
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
359
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
360
 
361
        TCP_init_socket eax
362
        ret
363
 
364
 
365
align 4
366
  .ip:
367
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
368
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
369
        ret
370
 
371
 
372
align 4
373
  .icmp:
374
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
375
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
376
        ret
377
 
378
align 4
379
  .pppoe:
380
        push    eax
381
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
382
        pop     eax
383
 
384
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
385
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
386
        ret
387
 
388
 
389
;-----------------------------------------------------------------
390
;
391
; SOCKET_bind
392
;
393
;  IN:  socket number in ecx
394
;       pointer to sockaddr struct in edx
395
;       length of that struct in esi
396
;  OUT: 0 on success
397
;
398
;-----------------------------------------------------------------
399
align 4
400
SOCKET_bind:
401
 
3556 hidnplayr 402
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 403
 
404
        call    SOCKET_num_to_ptr
405
        jz      s_error
406
 
407
        cmp     esi, 2
408
        jb      s_error
409
 
410
        cmp     word [edx], AF_INET4
411
        je      .af_inet4
412
 
413
        cmp     word [edx], AF_LOCAL
414
        je      .af_local
415
 
416
        jmp     s_error
417
 
418
  .af_local:
419
        ; TODO: write code here
420
 
421
        mov     dword [esp+32], 0
422
        ret
423
 
424
  .af_inet4:
425
 
426
        cmp     esi, 6
427
        jb      s_error
428
 
429
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
430
        je      .udp
431
 
432
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
433
        je      .tcp
434
 
435
        jmp     s_error
436
 
437
  .tcp:
438
  .udp:
439
 
3637 hidnplayr 440
        mov     ebx, [edx + 4]                  ; First, fill in the IP
3545 hidnplayr 441
        test    ebx, ebx                        ; If IP is 0, use default
442
        jnz     @f
3601 hidnplayr 443
        mov     ebx, [IP_LIST + 4]      ;;;;; FIXME !i!i!i
3545 hidnplayr 444
       @@:
445
        mov     [eax + IP_SOCKET.LocalIP], ebx
446
 
447
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
448
        call    SOCKET_check_port
449
        jz      s_error                         ; ZF is set by socket_check_port, on error
450
 
3556 hidnplayr 451
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3545 hidnplayr 452
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
453
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
454
 
455
        mov     dword [esp+32], 0
456
        ret
457
 
458
 
459
 
460
 
461
;-----------------------------------------------------------------
462
;
463
; SOCKET_connect
464
;
465
;  IN:  socket number in ecx
466
;       pointer to sockaddr struct in edx
467
;       length of that struct in esi
468
;  OUT: 0 on success
469
;
470
;-----------------------------------------------------------------
471
align 4
472
SOCKET_connect:
473
 
3556 hidnplayr 474
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 475
 
476
        call    SOCKET_num_to_ptr
477
        jz      s_error
478
 
479
        cmp     esi, 8
480
        jb      s_error
481
 
482
        cmp     word [edx], AF_INET4
483
        je      .af_inet4
484
 
485
        jmp     s_error
486
 
487
  .af_inet4:
488
        cmp     [eax + IP_SOCKET.LocalIP], 0
489
        jne     @f
3601 hidnplayr 490
        push    [IP_LIST + 4]                               ; FIXME !i!i!i!
3545 hidnplayr 491
        pop     [eax + IP_SOCKET.LocalIP]
492
       @@:
493
 
494
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
495
        je      .udp
496
 
497
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
498
        je      .tcp
499
 
500
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
501
        je      .ip
502
 
503
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
504
        je      .ip
505
 
506
        jmp     s_error
507
 
508
align 4
509
  .udp:
510
        pusha
511
        lea     ecx, [eax + SOCKET.mutex]
512
        call    mutex_lock
513
        popa
514
 
515
        pushw   [edx + 2]
516
        pop     [eax + UDP_SOCKET.RemotePort]
517
 
518
        pushd   [edx + 4]
519
        pop     [eax + IP_SOCKET.RemoteIP]
520
 
521
        cmp     [eax + UDP_SOCKET.LocalPort], 0
522
        jne     @f
523
        call    SOCKET_find_port
524
       @@:
525
 
526
        mov     [eax + UDP_SOCKET.firstpacket], 0
527
 
528
        push    eax
529
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
530
        pop     eax
531
 
532
        lea     ecx, [eax + SOCKET.mutex]
533
        call    mutex_unlock
534
 
535
        mov     dword [esp+32], 0
536
        ret
537
 
538
align 4
539
  .tcp:
540
        pusha
541
        lea     ecx, [eax + SOCKET.mutex]
542
        call    mutex_lock
543
        popa
544
 
545
        pushw   [edx + 2]
546
        pop     [eax + TCP_SOCKET.RemotePort]
547
 
548
        pushd   [edx + 4]
549
        pop     [eax + IP_SOCKET.RemoteIP]
550
 
551
        cmp     [eax + TCP_SOCKET.LocalPort], 0
552
        jne     @f
553
        call    SOCKET_find_port
554
       @@:
555
 
556
        mov     [eax + TCP_SOCKET.timer_persist], 0
557
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
558
 
559
        push    [TCP_sequence_num]
560
        add     [TCP_sequence_num], 6400
561
        pop     [eax + TCP_SOCKET.ISS]
562
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
563
 
564
 
565
        TCP_sendseqinit eax
566
 
567
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
568
 
569
        mov     ebx, eax
570
 
571
        lea     eax, [ebx + STREAM_SOCKET.snd]
572
        call    SOCKET_ring_create
573
 
574
        lea     eax, [ebx + STREAM_SOCKET.rcv]
575
        call    SOCKET_ring_create
576
 
577
        pusha
578
        lea     ecx, [ebx + SOCKET.mutex]
579
        call    mutex_unlock
580
        popa
581
 
582
        mov     eax, ebx
583
        call    TCP_output
584
 
585
;;; TODO: wait for successfull connection if blocking socket
586
 
587
        mov     dword [esp+32], 0
588
        ret
589
 
590
align 4
591
  .ip:
592
        pusha
593
        lea     ecx, [eax + SOCKET.mutex]
594
        call    mutex_lock
595
        popa
596
 
597
        pushd   [edx + 4]
598
        pop     [eax + IP_SOCKET.RemoteIP]
599
 
600
        push    eax
601
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
602
        pop     eax
603
 
604
        lea     ecx, [eax + SOCKET.mutex]
605
        call    mutex_unlock
606
 
607
        mov     dword [esp+32], 0
608
        ret
609
 
610
 
611
;-----------------------------------------------------------------
612
;
613
; SOCKET_listen
614
;
615
;  IN:  socket number in ecx
616
;       backlog in edx
617
;  OUT: eax is socket num, -1 on error
618
;
619
;-----------------------------------------------------------------
620
align 4
621
SOCKET_listen:
622
 
3556 hidnplayr 623
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 624
 
625
        call    SOCKET_num_to_ptr
626
        jz      s_error
627
 
628
        cmp     [eax + SOCKET.Domain], AF_INET4
629
        jne     s_error
630
 
631
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
632
        jne     s_error
633
 
634
        cmp     [eax + TCP_SOCKET.LocalPort], 0
635
        je      s_error
636
 
637
        cmp     [eax + IP_SOCKET.LocalIP], 0
638
        jne     @f
3601 hidnplayr 639
        push    [IP_LIST + 4]           ;;; fixme!!!!
3545 hidnplayr 640
        pop     [eax + IP_SOCKET.LocalIP]
641
       @@:
642
 
643
        cmp     edx, MAX_backlog
644
        jbe     @f
645
        mov     edx, MAX_backlog
646
       @@:
647
 
648
        mov     [eax + SOCKET.backlog], dx
649
        or      [eax + SOCKET.options], SO_ACCEPTCON
650
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
651
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
652
 
653
        push    eax
654
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
655
        pop     eax
656
 
657
        mov     dword [esp+32], 0
658
 
659
        ret
660
 
661
 
662
;-----------------------------------------------------------------
663
;
664
; SOCKET_accept
665
;
666
;  IN:  socket number in ecx
667
;       addr in edx
668
;       addrlen in esi
669
;  OUT: eax is socket num, -1 on error
670
;
671
;-----------------------------------------------------------------
672
align 4
673
SOCKET_accept:
674
 
3556 hidnplayr 675
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 676
 
677
        call    SOCKET_num_to_ptr
678
        jz      s_error
679
 
680
        test    [eax + SOCKET.options], SO_ACCEPTCON
681
        jz      s_error
682
 
683
        cmp     [eax + SOCKET.Domain], AF_INET4
684
        jne     s_error
685
 
686
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
687
        jne     s_error
688
 
689
  .loop:
690
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
691
 
692
; Ok, we got a socket ptr
693
        mov     eax, [esi]
694
 
695
; Change thread ID to that of the current thread
696
        mov     ebx, [TASK_BASE]
697
        mov     ebx, [ebx + TASKDATA.pid]
698
        mov     [eax + SOCKET.TID], ebx
699
 
700
; Convert it to a socket number
701
        call    SOCKET_ptr_to_num
702
        jz      s_error
703
; and return it to caller
704
        mov     [esp+32], eax
705
        ret
706
 
707
  .block:
708
        test    [eax + SOCKET.options], SO_NONBLOCK
709
        jnz     s_error
710
 
711
        call    SOCKET_block
712
        jmp     .loop
713
 
714
;-----------------------------------------------------------------
715
;
716
; SOCKET_close
717
;
718
;  IN:  socket number in ecx
719
;  OUT: eax is socket num, -1 on error
720
;
721
;-----------------------------------------------------------------
722
align 4
723
SOCKET_close:
724
 
3556 hidnplayr 725
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 726
 
727
        call    SOCKET_num_to_ptr
728
        jz      s_error
729
 
730
        mov     dword [esp+32], 0                               ; The socket exists, so we will succeed in closing it.
731
 
732
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
733
 
734
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
735
        jz      @f
736
        call    SOCKET_notify.unblock                           ; Unblock it.
737
  @@:
738
 
739
        cmp     [eax + SOCKET.Domain], AF_INET4
740
        jne     .free
741
 
742
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
743
        je      .tcp
744
 
745
  .free:
746
        call    SOCKET_free
747
        ret
748
 
749
  .tcp:
750
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
751
        jb      .free
752
 
753
        call    TCP_usrclosed
754
        call    TCP_output      ;;;; Fixme: is this nescessary??
3646 hidnplayr 755
        call    SOCKET_free
3545 hidnplayr 756
 
757
        ret
758
 
759
 
760
;-----------------------------------------------------------------
761
;
762
; SOCKET_receive
763
;
764
;  IN:  socket number in ecx
765
;       addr to buffer in edx
766
;       length of buffer in esi
767
;       flags in edi
768
;  OUT: eax is number of bytes copied, -1 on error
769
;
770
;-----------------------------------------------------------------
771
align 4
772
SOCKET_receive:
773
 
3556 hidnplayr 774
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 775
 
776
        call    SOCKET_num_to_ptr
777
        jz      s_error
778
 
3565 hidnplayr 779
        call    [eax + SOCKET.rcv_proc]
3545 hidnplayr 780
 
3565 hidnplayr 781
        mov     [esp+32], eax
782
        ret
3545 hidnplayr 783
 
3565 hidnplayr 784
 
3545 hidnplayr 785
align 4
786
SOCKET_receive_dgram:
787
 
3556 hidnplayr 788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 789
 
790
        mov     ebx, esi
791
        mov     edi, edx                                        ; addr to buffer
792
 
793
  .loop:
794
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block      ; destroys esi and ecx
795
 
796
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 797
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 798
 
799
        cmp     ecx, ebx
800
        ja      .too_small
801
 
3565 hidnplayr 802
        push    ecx
3545 hidnplayr 803
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
804
        mov     esi, [esi + socket_queue_entry.data_ptr]
3556 hidnplayr 805
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 806
 
807
; copy the data
808
        shr     ecx, 1
809
        jnc     .nb
810
        movsb
811
  .nb:
812
        shr     ecx, 1
813
        jnc     .nw
814
        movsw
815
  .nw:
816
        test    ecx, ecx
817
        jz      .nd
818
        rep     movsd
819
  .nd:
820
 
821
        call    kernel_free                                     ; remove the packet
3565 hidnplayr 822
        pop     eax
823
 
3545 hidnplayr 824
        ret
825
 
826
  .too_small:
827
 
3556 hidnplayr 828
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n"
3565 hidnplayr 829
  .fail:
830
        mov     eax, -1
831
        ret
3545 hidnplayr 832
 
833
  .block:
834
        test    [eax + SOCKET.options], SO_NONBLOCK
3565 hidnplayr 835
        jnz     .fail
3545 hidnplayr 836
 
837
        call    SOCKET_block
838
        jmp     .loop
839
 
840
 
841
align 4
842
SOCKET_receive_local:
843
 
844
        ; does this socket have a PID yet?
845
        cmp     [eax + SOCKET.PID], 0
846
        jne     @f
847
 
848
        ; Change PID to that of current process
849
        mov     ebx, [TASK_BASE]
850
        mov     ebx, [ebx + TASKDATA.pid]
851
        mov     [eax + SOCKET.PID], ebx
852
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
853
      @@:
854
 
855
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
856
 
857
align 4
858
SOCKET_receive_stream:
859
 
3556 hidnplayr 860
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 861
 
862
        mov     ebx, edi
863
        mov     ecx, esi
864
        mov     edi, edx
865
        xor     edx, edx
866
 
867
        test    ebx, MSG_DONTWAIT
868
        jnz     .dontwait
869
  .loop:
870
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
871
        je      .block
872
  .dontwait:
873
        test    ebx, MSG_PEEK
874
        jnz     .peek
875
 
876
        add     eax, STREAM_SOCKET.rcv
877
        call    SOCKET_ring_read
878
        call    SOCKET_ring_free
879
 
3565 hidnplayr 880
        mov     eax, ecx                ; return number of bytes copied
3545 hidnplayr 881
        ret
882
 
883
  .peek:
3565 hidnplayr 884
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3545 hidnplayr 885
        ret
886
 
887
  .block:
888
        test    [eax + SOCKET.options], SO_NONBLOCK
889
        jnz     .return0
890
 
891
        call    SOCKET_block
892
        jmp     .loop
893
 
894
  .return0:
3565 hidnplayr 895
        test    [eax + SOCKET.options], SS_CANTRCVMORE
896
        jz      .ok
897
 
898
        xor     eax, eax
899
        dec     eax
3545 hidnplayr 900
        ret
901
 
3565 hidnplayr 902
  .ok:
903
        xor     eax, eax
904
        ret
3545 hidnplayr 905
 
3565 hidnplayr 906
 
3545 hidnplayr 907
;-----------------------------------------------------------------
908
;
909
; SOCKET_send
910
;
911
;
912
;  IN:  socket number in ecx
913
;       pointer to data in edx
914
;       datalength in esi
915
;       flags in edi
916
;  OUT: -1 on error
917
;
918
;-----------------------------------------------------------------
919
align 4
920
SOCKET_send:
921
 
3556 hidnplayr 922
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 923
 
924
        call    SOCKET_num_to_ptr
925
        jz      s_error
926
 
927
        mov     ecx, esi
928
        mov     esi, edx
929
 
930
        jmp     [eax + SOCKET.snd_proc]
931
 
932
 
933
align 4
934
SOCKET_send_udp:
935
 
3556 hidnplayr 936
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 937
 
938
        mov     [esp+32], ecx
939
        call    UDP_output
940
        cmp     eax, -1
941
        je      s_error
942
        ret
943
 
944
 
945
align 4
946
SOCKET_send_tcp:
947
 
3556 hidnplayr 948
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 949
 
950
        push    eax
951
        add     eax, STREAM_SOCKET.snd
952
        call    SOCKET_ring_write
953
        pop     eax
954
 
955
        mov     [esp+32], ecx
956
 
957
        call    TCP_output
958
        ret
959
 
960
 
961
align 4
962
SOCKET_send_ip:
963
 
3556 hidnplayr 964
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 965
 
966
        mov     [esp+32], ecx
967
        call    IPv4_output_raw
968
        cmp     eax, -1
969
        je      s_error
970
        ret
971
 
972
 
973
align 4
974
SOCKET_send_icmp:
975
 
3556 hidnplayr 976
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 977
 
978
        mov     [esp+32], ecx
979
        call    ICMP_output_raw
980
        cmp     eax, -1
981
        je      s_error
982
        ret
983
 
984
 
985
align 4
986
SOCKET_send_pppoe:
987
 
3556 hidnplayr 988
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 989
 
990
        mov     [esp+32], ecx
991
        mov     ebx, [eax + SOCKET.device]
992
 
993
        call    PPPoE_discovery_output
994
        cmp     eax, -1
995
        je      s_error
996
        ret
997
 
998
 
999
 
1000
align 4
1001
SOCKET_send_local:
1002
 
1003
        ; does this socket have a PID yet?
1004
        cmp     [eax + SOCKET.PID], 0
1005
        jne     @f
1006
 
1007
        ; Change PID to that of current process
1008
        mov     ebx, [TASK_BASE]
1009
        mov     ebx, [ebx + TASKDATA.pid]
1010
        mov     [eax + SOCKET.PID], ebx
1011
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1012
      @@:
1013
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
1014
 
1015
align 4
1016
SOCKET_send_local_:
1017
 
3556 hidnplayr 1018
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1019
 
1020
        ; get the other side's socket and check if it still exists
1021
        mov     eax, [eax + SOCKET.device]
1022
        call    SOCKET_check
1023
        jz      s_error
1024
 
1025
        ; allright, shove in the data!
1026
        push    eax
1027
        add     eax, STREAM_SOCKET.rcv
1028
        call    SOCKET_ring_write
1029
        pop     eax
1030
 
1031
        ; return the number of written bytes (or errorcode) to application
1032
        mov     [esp+32], ecx
1033
 
1034
        ; and notify the other end
1035
        call    SOCKET_notify
1036
 
1037
        ret
1038
 
1039
 
1040
;-----------------------------------------------------------------
1041
;
1042
; SOCKET_get_options
1043
;
1044
;  IN:  ecx = socket number
1045
;       edx = pointer to the options:
1046
;               dd      level, optname, optval, optlen
1047
;  OUT: -1 on error
1048
;
1049
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1050
; TODO: find best way to notify that send()'ed data were acknowledged
1051
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1052
;
1053
;-----------------------------------------------------------------
1054
align 4
1055
SOCKET_get_opt:
1056
 
3556 hidnplayr 1057
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1058
 
1059
        call    SOCKET_num_to_ptr
1060
        jz      s_error
1061
 
1062
        cmp     dword [edx], IP_PROTO_TCP
1063
        jne     s_error
1064
        cmp     dword [edx+4], -2
1065
        je      @f
1066
        cmp     dword [edx+4], -3
1067
        jne     s_error
1068
@@:
1069
;        mov     eax, [edx+12]
1070
;        test    eax, eax
1071
;        jz      .fail
1072
;        cmp     dword [eax], 4
1073
;        mov     dword [eax], 4
1074
;        jb      .fail
1075
;        stdcall net_socket_num_to_addr, ecx
1076
;        test    eax, eax
1077
;        jz      .fail
1078
;        ; todo: check that eax is really TCP socket
1079
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1080
;        cmp     dword [edx+4], -2
1081
;        jz      @f
1082
;        mov     ecx, [eax + TCP_SOCKET.state]
1083
@@:
1084
        mov     eax, [edx+8]
1085
        test    eax, eax
1086
        jz      @f
1087
        mov     [eax], ecx
1088
@@:
1089
        mov     dword [esp+32], 0
1090
        ret
1091
 
1092
 
1093
 
1094
;-----------------------------------------------------------------
1095
;
1096
; SOCKET_set_options
1097
;
1098
;  IN:  ecx = socket number
1099
;       edx = pointer to the options:
1100
;               dd      level, optname, optlen, optval
1101
;  OUT: -1 on error
1102
;
1103
;-----------------------------------------------------------------
1104
align 4
1105
SOCKET_set_opt:
1106
 
3556 hidnplayr 1107
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1108
 
1109
        call    SOCKET_num_to_ptr
1110
        jz      s_error
1111
 
1112
        cmp     dword [edx], SOL_SOCKET
1113
        jne     s_error
1114
 
1115
        cmp     dword [edx+4], SO_BINDTODEVICE
1116
        je      .bind
1117
 
1118
        cmp     dword [edx+4], SO_BLOCK
1119
        je      .block
1120
 
1121
        jmp     s_error
1122
 
1123
  .bind:
1124
        cmp     dword [edx+8], 0
1125
        je      .unbind
1126
 
1127
        movzx   edx, byte [edx + 9]
3600 hidnplayr 1128
        cmp     edx, NET_DEVICES_MAX
3545 hidnplayr 1129
        ja      s_error
1130
 
1131
        mov     edx, [NET_DRV_LIST + 4*edx]
1132
        test    edx, edx
1133
        jz      s_error
1134
        mov     [eax + SOCKET.device], edx
1135
 
3556 hidnplayr 1136
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3545 hidnplayr 1137
 
1138
        mov     dword [esp+32], 0       ; success!
1139
        ret
1140
 
1141
  .unbind:
1142
        mov     [eax + SOCKET.device], 0
1143
 
1144
        mov     dword [esp+32], 0       ; success!
1145
        ret
1146
 
1147
  .block:
1148
        cmp     dword [edx+8], 0
1149
        je      .unblock
1150
 
1151
        and     [eax + SOCKET.options], not SO_NONBLOCK
1152
 
1153
        mov     dword [esp+32], 0       ; success!
1154
        ret
1155
 
1156
  .unblock:
1157
        or      [eax + SOCKET.options], SO_NONBLOCK
1158
 
1159
        mov     dword [esp+32], 0       ; success!
1160
        ret
1161
 
1162
 
1163
 
1164
;-----------------------------------------------------------------
1165
;
1166
; SOCKET_pair
1167
;
1168
; Allocates a pair of linked LOCAL domain sockets
1169
;
1170
; IN: /
1171
; OUT: eax is socket1 num, -1 on error
1172
;      ebx is socket2 num
1173
;
1174
;-----------------------------------------------------------------
1175
align 4
1176
SOCKET_pair:
1177
 
3556 hidnplayr 1178
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1179
 
1180
        call    SOCKET_alloc
1181
        jz      s_error
1182
        mov     [esp+32], edi   ; application's eax
1183
 
1184
        mov     [eax + SOCKET.Domain], AF_LOCAL
1185
        mov     [eax + SOCKET.Type], SOCK_STREAM
1186
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1187
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1188
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1189
        mov     [eax + SOCKET.PID], 0
1190
        mov     ebx, eax
1191
 
1192
        call    SOCKET_alloc
1193
        jz      .error
1194
        mov     [esp+24], edi   ; application's ebx
1195
 
1196
        mov     [eax + SOCKET.Domain], AF_LOCAL
1197
        mov     [eax + SOCKET.Type], SOCK_STREAM
1198
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1199
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1200
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1201
        mov     [eax + SOCKET.PID], 0
1202
 
1203
        ; Link the two sockets to eachother
1204
        mov     [eax + SOCKET.device], ebx
1205
        mov     [ebx + SOCKET.device], eax
1206
 
1207
        lea     eax, [eax + STREAM_SOCKET.rcv]
1208
        call    SOCKET_ring_create
1209
 
1210
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1211
        call    SOCKET_ring_create
1212
        pop     eax
1213
 
1214
        ret
1215
 
1216
  .error:
1217
        mov     eax, ebx
1218
        call    SOCKET_free
1219
        jmp     s_error
1220
 
1221
 
1222
 
1223
;-----------------------------------------------------------------
1224
;
1225
; SOCKET_debug
1226
;
1227
;  Copies socket variables to application buffer
1228
;
1229
;  IN:  ecx = socket number
1230
;       edx = pointer to buffer
1231
;
1232
;  OUT: -1 on error
1233
;-----------------------------------------------------------------
1234
align 4
1235
SOCKET_debug:
1236
 
3556 hidnplayr 1237
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1238
 
1239
        mov     edi, edx
1240
 
1241
        test    ecx, ecx
1242
        jz      .returnall
1243
 
1244
        call    SOCKET_num_to_ptr
1245
        jz      s_error
1246
 
1247
        mov     esi, eax
1248
        mov     ecx, SOCKETBUFFSIZE/4
1249
        rep     movsd
1250
 
1251
        mov     dword [esp+32], 0
1252
        ret
1253
 
1254
  .returnall:
1255
        mov     ebx, net_sockets
1256
  .next_socket:
1257
        mov     ebx, [ebx + SOCKET.NextPtr]
1258
        test    ebx, ebx
1259
        jz      .done
1260
        mov     eax, [ebx + SOCKET.Number]
1261
        stosd
1262
        jmp     .next_socket
1263
  .done:
1264
        xor     eax, eax
1265
        stosd
1266
 
1267
        mov     dword [esp+32], 0
1268
        ret
1269
 
1270
 
1271
;-----------------------------------------------------------------
1272
;
1273
; SOCKET_find_port
1274
;
1275
; Fills in the local port number for TCP and UDP sockets
1276
; This procedure always works because the number of sockets is
1277
; limited to a smaller number then the number of possible ports
1278
;
1279
;  IN:  eax = socket pointer
1280
;  OUT: /
1281
;
1282
;-----------------------------------------------------------------
1283
align 4
1284
SOCKET_find_port:
1285
 
3556 hidnplayr 1286
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1287
 
1288
        push    ebx esi ecx
1289
 
1290
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1291
        je      .udp
1292
 
1293
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1294
        je      .tcp
1295
 
1296
        pop     ecx esi ebx
1297
        ret
1298
 
1299
  .udp:
1300
        mov     bx, [last_UDP_port]
1301
        call    .findit
1302
        mov     [last_UDP_port], bx
1303
 
1304
        pop     ecx esi ebx
1305
        ret
1306
 
1307
  .tcp:
1308
        mov     bx, [last_TCP_port]
1309
        call    .findit
1310
        mov     [last_TCP_port], bx
1311
 
1312
        pop     ecx esi ebx
1313
        ret
1314
 
1315
 
1316
  .restart:
1317
        mov     bx, MIN_EPHEMERAL_PORT_N
1318
  .findit:
1319
        cmp     bx, MAX_EPHEMERAL_PORT_N
1320
        je      .restart
1321
 
1322
        add     bh, 1
1323
        adc     bl, 0
1324
 
1325
        call    SOCKET_check_port
1326
        jz      .findit
1327
        ret
1328
 
1329
 
1330
 
1331
;-----------------------------------------------------------------
1332
;
1333
; SOCKET_check_port (to be used with AF_INET only!)
1334
;
1335
; Checks if a local port number is unused
1336
; If the proposed port number is unused, it is filled in in the socket structure
1337
;
1338
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1339
;        bx = proposed socket number (network byte order)
1340
;
1341
;  OUT:  ZF = set on error
1342
;
1343
;-----------------------------------------------------------------
1344
align 4
1345
SOCKET_check_port:
1346
 
3556 hidnplayr 1347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1348
 
3647 hidnplayr 1349
        pusha
1350
        mov     ecx, socket_mutex
1351
        call    mutex_lock
1352
        popa
1353
 
3545 hidnplayr 1354
        mov     ecx, [eax + SOCKET.Protocol]
1355
        mov     edx, [eax + IP_SOCKET.LocalIP]
1356
        mov     esi, net_sockets
1357
 
1358
  .next_socket:
1359
        mov     esi, [esi + SOCKET.NextPtr]
1360
        or      esi, esi
1361
        jz      .port_ok
1362
 
1363
        cmp     [esi + SOCKET.Protocol], ecx
1364
        jne     .next_socket
1365
 
1366
        cmp     [esi + IP_SOCKET.LocalIP], edx
1367
        jne     .next_socket
1368
 
1369
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1370
        jne     .next_socket
1371
 
3647 hidnplayr 1372
        pusha
1373
        mov     ecx, socket_mutex
1374
        call    mutex_unlock
1375
        popa
1376
 
3556 hidnplayr 1377
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1378
        ret
1379
 
1380
  .port_ok:
3647 hidnplayr 1381
        pusha
1382
        mov     ecx, socket_mutex
1383
        call    mutex_unlock
1384
        popa
1385
 
3556 hidnplayr 1386
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1387
        mov     [eax + UDP_SOCKET.LocalPort], bx
1388
        or      bx, bx                                  ; clear the zero-flag
1389
        ret
1390
 
1391
 
1392
 
1393
;-----------------------------------------------------------------
1394
;
1395
; SOCKET_input
1396
;
1397
; Updates a (stateless) socket with received data
1398
;
1399
; Note: the mutex should already be set !
1400
;
1401
;  IN:  eax = socket ptr
1402
;       ecx = data size
1403
;       esi = ptr to data
1404
;       [esp] = ptr to buf
1405
;       [esp + 4] = buf size
1406
;
1407
;  OUT: /
1408
;
1409
;-----------------------------------------------------------------
1410
align 4
1411
SOCKET_input:
1412
 
3556 hidnplayr 1413
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1414
 
1415
        mov     [esp+4], ecx
1416
        push    esi
1417
        mov     esi, esp
1418
 
1419
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1420
 
3556 hidnplayr 1421
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1422
        add     esp, sizeof.socket_queue_entry
1423
 
1424
        pusha
1425
        lea     ecx, [eax + SOCKET.mutex]
1426
        call    mutex_unlock
1427
        popa
1428
 
1429
        jmp     SOCKET_notify
1430
 
1431
  .full:
3556 hidnplayr 1432
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1433
 
1434
        pusha
1435
        lea     ecx, [eax + SOCKET.mutex]
1436
        call    mutex_unlock
1437
        popa
1438
 
1439
        call    kernel_free
1440
        add     esp, 8
1441
 
1442
        ret
1443
 
1444
 
1445
;--------------------------
1446
;
1447
; eax = ptr to ring struct (just a buffer of the right size)
1448
;
1449
align 4
1450
SOCKET_ring_create:
1451
 
1452
        push    esi
1453
        mov     esi, eax
1454
 
1455
        push    edx
1456
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1457
        pop     edx
1458
 
3556 hidnplayr 1459
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3545 hidnplayr 1460
 
1461
        pusha
1462
        lea     ecx, [esi + RING_BUFFER.mutex]
1463
        call    mutex_init
1464
        popa
1465
 
1466
        mov     [esi + RING_BUFFER.start_ptr], eax
1467
        mov     [esi + RING_BUFFER.write_ptr], eax
1468
        mov     [esi + RING_BUFFER.read_ptr], eax
1469
        mov     [esi + RING_BUFFER.size], 0
1470
        add     eax, SOCKET_MAXDATA
1471
        mov     [esi + RING_BUFFER.end_ptr], eax
1472
        mov     eax, esi
1473
        pop     esi
1474
 
1475
        ret
1476
 
1477
;-----------------------------------------------------------------
1478
;
1479
; SOCKET_ring_write
1480
;
1481
; Adds data to a stream socket, and updates write pointer and size
1482
;
1483
;  IN:  eax = ptr to ring struct
1484
;       ecx = data size
1485
;       esi = ptr to data
1486
;
1487
;  OUT: ecx = number of bytes stored
1488
;
1489
;-----------------------------------------------------------------
1490
align 4
1491
SOCKET_ring_write:
1492
 
3556 hidnplayr 1493
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1494
 
1495
; lock mutex
1496
        pusha
1497
        lea     ecx, [eax + RING_BUFFER.mutex]
1498
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1499
        popa
1500
 
1501
; calculate available size
1502
        mov     edi, SOCKET_MAXDATA
1503
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1504
        cmp     ecx, edi
1505
        jbe     .copy
1506
        mov     ecx, edi
1507
  .copy:
1508
        mov     edi, [eax + RING_BUFFER.write_ptr]
3556 hidnplayr 1509
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1510
 
1511
; update write ptr
1512
        push    edi
1513
        add     edi, ecx
1514
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1515
        jb      @f
1516
        sub     edi, SOCKET_MAXDATA                             ; WRAP
1517
  @@:
1518
        mov     [eax + RING_BUFFER.write_ptr], edi
1519
        pop     edi
1520
 
1521
; update size
1522
        add     [eax + RING_BUFFER.size], ecx
1523
 
1524
; copy the data
1525
        push    ecx
1526
        shr     ecx, 1
1527
        jnc     .nb
1528
        movsb
1529
  .nb:
1530
        shr     ecx, 1
1531
        jnc     .nw
1532
        movsw
1533
  .nw:
1534
        test    ecx, ecx
1535
        jz      .nd
1536
        rep     movsd
1537
  .nd:
1538
        pop     ecx
1539
 
1540
; unlock mutex
1541
        push    eax ecx
1542
        lea     ecx, [eax + RING_BUFFER.mutex]
1543
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1544
        pop     ecx eax
1545
 
1546
        ret
1547
 
1548
;-----------------------------------------------------------------
1549
;
1550
; SOCKET_ring_read
1551
;
1552
;  IN:  eax = ring struct ptr
1553
;       ecx = bytes to read
1554
;       edx = offset
1555
;       edi = ptr to buffer start
1556
;
1557
;  OUT: eax = unchanged
1558
;       ecx = number of bytes read (0 on error)
1559
;       edx = destroyed
1560
;       esi = destroyed
1561
;       edi = ptr to buffer end
1562
;
1563
;-----------------------------------------------------------------
1564
align 4
1565
SOCKET_ring_read:
1566
 
3556 hidnplayr 1567
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1568
 
1569
        pusha
1570
        lea     ecx, [eax + RING_BUFFER.mutex]
1571
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1572
        popa
1573
 
1574
        mov     esi, [eax + RING_BUFFER.read_ptr]
1575
        add     esi, edx                                        ; esi = start_ptr + offset
1576
 
1577
        neg     edx
1578
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1579
        jle     .no_data_at_all
1580
 
1581
        pusha
1582
        lea     ecx, [eax + RING_BUFFER.mutex]
1583
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1584
        popa
1585
 
1586
        cmp     ecx, edx
1587
        ja      .less_data
1588
 
1589
  .copy:
3556 hidnplayr 1590
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1591
        push    ecx
1592
        shr     ecx, 1
1593
        jnc     .nb
1594
        movsb
1595
  .nb:
1596
        shr     ecx, 1
1597
        jnc     .nw
1598
        movsw
1599
  .nw:
1600
        test    ecx, ecx
1601
        jz      .nd
1602
        rep     movsd
1603
  .nd:
1604
        pop     ecx
1605
        ret
1606
 
1607
  .no_data_at_all:
1608
        pusha
1609
        lea     ecx, [eax + RING_BUFFER.mutex]
1610
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1611
        popa
1612
 
3556 hidnplayr 1613
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1614
        xor     ecx, ecx
1615
        ret
1616
 
1617
  .less_data:
1618
        mov     ecx, edx
1619
        jmp     .copy
1620
 
1621
 
1622
;-----------------------------------------------------------------
1623
;
1624
; SOCKET_ring_free
1625
;
1626
; Free's some bytes from the ringbuffer
1627
;
1628
;  IN:  eax = ptr to ring struct
1629
;       ecx = data size
1630
;
1631
;  OUT: ecx = number of bytes free-ed
1632
;
1633
;-----------------------------------------------------------------
1634
align 4
1635
SOCKET_ring_free:
1636
 
3556 hidnplayr 1637
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1638
 
1639
        push    eax ecx
1640
        lea     ecx, [eax + RING_BUFFER.mutex]
1641
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1642
        pop     ecx eax
1643
 
1644
        sub     [eax + RING_BUFFER.size], ecx
1645
        jb      .error
1646
        add     [eax + RING_BUFFER.read_ptr], ecx
1647
 
1648
        mov     edx, [eax + RING_BUFFER.end_ptr]
1649
        cmp     [eax + RING_BUFFER.read_ptr], edx
1650
        jb      @f
1651
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1652
       @@:
1653
 
1654
        push    eax ecx
1655
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1656
        call    mutex_unlock
1657
        pop     ecx eax
1658
 
1659
        ret
1660
 
1661
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3556 hidnplayr 1662
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1663
        add     [eax + RING_BUFFER.size], ecx
1664
 
1665
        push    eax
1666
        lea     ecx, [eax + RING_BUFFER.mutex]
1667
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1668
        pop     eax
1669
 
1670
        xor     ecx, ecx
1671
        ret
1672
 
1673
 
1674
;-----------------------------------------------------------------
1675
;
1676
; SOCKET_block
1677
;
1678
; Suspends the thread attached to a socket
1679
;
1680
;  IN:  eax = socket ptr
1681
;  OUT: /
1682
;
1683
;-----------------------------------------------------------------
1684
align 4
1685
SOCKET_block:
1686
 
3556 hidnplayr 1687
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1688
 
1689
        pushf
1690
        cli
1691
 
1692
        ; Set the 'socket is blocked' flag
1693
        or      [eax + SOCKET.state], SS_BLOCKED
1694
 
1695
        ; Suspend the thread
1696
        push    edx
1697
        mov     edx, [TASK_BASE]
1698
        mov     [edx + TASKDATA.state], 1               ; Suspended
1699
 
1700
        ; Remember the thread ID so we can wake it up again
1701
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1702
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1703
        mov     [eax + SOCKET.TID], edx
1704
        pop     edx
1705
 
1706
        call    change_task
1707
        popf
1708
 
3556 hidnplayr 1709
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
3545 hidnplayr 1710
 
1711
        ret
1712
 
1713
 
1714
;-----------------------------------------------------------------
1715
;
1716
; SOCKET_notify
1717
;
1718
; notify's the owner of a socket that something happened
1719
;
1720
;  IN:  eax = socket ptr
1721
;  OUT: /
1722
;
1723
;-----------------------------------------------------------------
1724
align 4
1725
SOCKET_notify:
1726
 
3556 hidnplayr 1727
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1728
 
1729
        call    SOCKET_check
1730
        jz      .error
1731
 
1732
        test    [eax + SOCKET.state], SS_BLOCKED
1733
        jnz     .unblock
1734
 
1735
        test    [eax + SOCKET.options], SO_NONBLOCK
1736
        jz      .error
1737
 
1738
        push    eax ecx esi
1739
 
1740
; socket exists and is of non blocking type.
1741
; We'll try to flag an event to the thread
1742
 
1743
        mov     eax, [eax + SOCKET.TID]
1744
        test    eax, eax
1745
        jz      .done
1746
        mov     ecx, 1
1747
        mov     esi, TASK_DATA + TASKDATA.pid
1748
 
1749
  .next_pid:
1750
        cmp     [esi], eax
1751
        je      .found_pid
1752
        inc     ecx
1753
        add     esi, 0x20
1754
        cmp     ecx, [TASK_COUNT]
1755
        jbe     .next_pid
1756
; PID not found, TODO: close socket!
1757
        jmp     .done
1758
 
1759
  .found_pid:
1760
        shl     ecx, 8
1761
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1762
 
3556 hidnplayr 1763
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
3545 hidnplayr 1764
 
1765
        jmp     .done
1766
 
1767
  .unblock:
1768
        push    eax ecx esi
1769
        ; Clear the 'socket is blocked' flag
1770
        and     [eax + SOCKET.state], not SS_BLOCKED
1771
 
1772
        ; Find the thread's TASK_DATA
1773
        mov     eax, [eax + SOCKET.TID]
1774
        test    eax, eax
1775
        jz      .error
1776
        xor     ecx, ecx
1777
        inc     ecx
1778
        mov     esi, TASK_DATA
1779
  .next:
1780
        cmp     [esi + TASKDATA.pid], eax
1781
        je      .found
1782
        inc     ecx
1783
        add     esi, 0x20
1784
        cmp     ecx, [TASK_COUNT]
1785
        jbe     .next
1786
        jmp     .error
1787
  .found:
1788
 
1789
        ; Run the thread
1790
        mov     [esi + TASKDATA.state], 0       ; Running
3556 hidnplayr 1791
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
3545 hidnplayr 1792
 
1793
  .done:
1794
        pop     esi ecx eax
1795
 
1796
  .error:
1797
        ret
1798
 
1799
 
1800
;--------------------------------------------------------------------
1801
;
1802
; SOCKET_alloc
1803
;
1804
; Allocate memory for socket data and put new socket into the list
1805
; Newly created socket is initialized with calling PID and number and
1806
; put into beginning of list (which is a fastest way).
1807
;
1808
; IN:  /
1809
; OUT: eax = 0 on error, socket ptr otherwise
1810
;      edi = socket number
1811
;       ZF = cleared on error
1812
;
1813
;--------------------------------------------------------------------
1814
align 4
1815
SOCKET_alloc:
1816
 
1817
        push    ebx
1818
 
1819
        stdcall kernel_alloc, SOCKETBUFFSIZE
3556 hidnplayr 1820
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1821
        or      eax, eax
1822
        jz      .exit
1823
 
1824
; zero-initialize allocated memory
1825
        push    eax
1826
        mov     edi, eax
1827
        mov     ecx, SOCKETBUFFSIZE / 4
1828
        xor     eax, eax
1829
        rep     stosd
1830
        pop     eax
1831
 
1832
; set send-and receive procedures to return -1
1833
        mov     [eax + SOCKET.snd_proc], s_error
1834
        mov     [eax + SOCKET.rcv_proc], s_error
1835
 
3647 hidnplayr 1836
        pusha
1837
        mov     ecx, socket_mutex
1838
        call    mutex_lock
1839
        popa
1840
 
3545 hidnplayr 1841
; find first free socket number and use it
1842
        mov     edi, [last_socket_num]
1843
  .next_socket_number:
1844
        inc     edi
1845
        jz      .next_socket_number     ; avoid socket nr 0
1846
        cmp     edi, -1
1847
        je      .next_socket_number     ; avoid socket nr -1
1848
        mov     ebx, net_sockets
1849
  .next_socket:
1850
        mov     ebx, [ebx + SOCKET.NextPtr]
1851
        test    ebx, ebx
1852
        jz      .last_socket
1853
 
1854
        cmp     [ebx + SOCKET.Number], edi
1855
        jne     .next_socket
1856
        jmp     .next_socket_number
1857
 
1858
  .last_socket:
1859
        mov     [last_socket_num], edi
1860
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 1861
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 1862
 
1863
; Fill in PID
1864
        mov     ebx, [TASK_BASE]
1865
        mov     ebx, [ebx + TASKDATA.pid]
1866
        mov     [eax + SOCKET.PID], ebx
1867
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1868
 
1869
; init mutex
1870
        pusha
1871
        lea     ecx, [eax + SOCKET.mutex]
1872
        call    mutex_init
1873
        popa
1874
 
1875
; add socket to the list by re-arranging some pointers
1876
        mov     ebx, [net_sockets + SOCKET.NextPtr]
1877
 
1878
        mov     [eax + SOCKET.PrevPtr], net_sockets
1879
        mov     [eax + SOCKET.NextPtr], ebx
1880
 
1881
        test    ebx, ebx
1882
        jz      @f
1883
 
1884
        pusha
1885
        lea     ecx, [ebx + SOCKET.mutex]
1886
        call    mutex_lock
1887
        popa
1888
 
1889
        mov     [ebx + SOCKET.PrevPtr], eax
1890
 
1891
        pusha
1892
        lea     ecx, [ebx + SOCKET.mutex]
1893
        call    mutex_unlock
1894
        popa
1895
       @@:
1896
 
1897
        mov     [net_sockets + SOCKET.NextPtr], eax
1898
        or      eax, eax                ; used to clear zero flag
3647 hidnplayr 1899
 
1900
        pusha
1901
        mov     ecx, socket_mutex
1902
        call    mutex_unlock
1903
        popa
1904
 
3545 hidnplayr 1905
  .exit:
1906
        pop     ebx
1907
 
1908
        ret
1909
 
1910
 
1911
;----------------------------------------------------
1912
;
1913
; SOCKET_free
1914
;
1915
; Free socket data memory and remove socket from the list
1916
;
1917
; IN:  eax = socket ptr
1918
; OUT: /
1919
;
1920
;----------------------------------------------------
1921
align 4
1922
SOCKET_free:
1923
 
3556 hidnplayr 1924
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 1925
 
3652 hidnplayr 1926
        pusha
1927
        mov     ecx, socket_mutex
1928
        call    mutex_lock
1929
        popa
1930
 
3545 hidnplayr 1931
        call    SOCKET_check
1932
        jz      .error
1933
 
1934
        push    ebx
1935
 
1936
        pusha
1937
        lea     ecx, [eax + SOCKET.mutex]
1938
        call    mutex_lock
1939
        popa
1940
 
1941
        cmp     [eax + SOCKET.Domain], AF_INET4
1942
        jnz     .no_tcp
1943
 
1944
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1945
        jnz     .no_tcp
1946
 
1947
        mov     ebx, eax
1948
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
1949
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
1950
        mov     eax, ebx
1951
  .no_tcp:
1952
 
3652 hidnplayr 1953
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 1954
        push    eax                             ; this will be passed to kernel_free
1955
        mov     ebx, [eax + SOCKET.NextPtr]
1956
        mov     eax, [eax + SOCKET.PrevPtr]
1957
 
3556 hidnplayr 1958
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 1959
 
1960
        test    eax, eax
1961
        jz      @f
1962
        mov     [eax + SOCKET.NextPtr], ebx
1963
       @@:
1964
 
1965
        test    ebx, ebx
1966
        jz      @f
1967
        mov     [ebx + SOCKET.PrevPtr], eax
1968
       @@:
1969
 
1970
        call    kernel_free
1971
        pop     ebx
1972
 
3652 hidnplayr 1973
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
1974
 
1975
  .error:
1976
 
3647 hidnplayr 1977
        pusha
1978
        mov     ecx, socket_mutex
1979
        call    mutex_unlock
1980
        popa
1981
 
3545 hidnplayr 1982
        ret
1983
 
1984
;------------------------------------
1985
;
1986
; SOCKET_fork
1987
;
1988
; Create a child socket
1989
;
1990
; IN:  socket nr in ebx
1991
; OUT: child socket nr in eax
1992
;
1993
;-----------------------------------
1994
align 4
1995
SOCKET_fork:
1996
 
3556 hidnplayr 1997
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 1998
 
1999
; Exit if backlog queue is full
2000
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2001
        cmp     ax, [ebx + SOCKET.backlog]
2002
        jae     .fail
2003
 
2004
; Allocate new socket
2005
        push    ebx
2006
        call    SOCKET_alloc
2007
        pop     ebx
2008
        jz      .fail
2009
 
2010
        push    eax
2011
        mov     esi, esp
2012
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2013
        pop     eax
2014
 
2015
; Copy structure from current socket to new
2016
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
2017
        lea     esi, [ebx + SOCKET.PID]
2018
        lea     edi, [eax + SOCKET.PID]
2019
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
2020
        rep     movsd
2021
 
2022
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2023
 
2024
        ret
2025
 
2026
  .fail2:
2027
        add     esp, 4+4+4
2028
  .fail:
3556 hidnplayr 2029
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2030
        xor     eax, eax
2031
        ret
2032
 
2033
 
2034
;---------------------------------------------------
2035
;
2036
; SOCKET_num_to_ptr
2037
;
2038
; Get socket structure address by its number
2039
;
2040
; IN:  ecx = socket number
2041
; OUT: eax = 0 on error, socket ptr otherwise
2042
;       ZF = set on error
2043
;
2044
;---------------------------------------------------
2045
align 4
2046
SOCKET_num_to_ptr:
2047
 
3556 hidnplayr 2048
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2049
 
3647 hidnplayr 2050
        pusha
2051
        mov     ecx, socket_mutex
2052
        call    mutex_lock
2053
        popa
2054
 
3545 hidnplayr 2055
        mov     eax, net_sockets
2056
 
2057
  .next_socket:
2058
        mov     eax, [eax + SOCKET.NextPtr]
2059
        or      eax, eax
2060
        jz      .error
2061
        cmp     [eax + SOCKET.Number], ecx
2062
        jne     .next_socket
2063
 
2064
        test    eax, eax
2065
 
3647 hidnplayr 2066
        pusha
2067
        mov     ecx, socket_mutex
2068
        call    mutex_unlock
2069
        popa
2070
 
3556 hidnplayr 2071
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2072
        ret
2073
 
2074
  .error:
3647 hidnplayr 2075
        pusha
2076
        mov     ecx, socket_mutex
2077
        call    mutex_unlock
2078
        popa
2079
 
3637 hidnplayr 2080
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
3545 hidnplayr 2081
        ret
2082
 
2083
 
2084
;---------------------------------------------------
2085
;
2086
; SOCKET_ptr_to_num
2087
;
2088
; Get socket number by its address
2089
;
2090
; IN:  eax = socket ptr
2091
; OUT: eax = 0 on error, socket num otherwise
2092
;       ZF = set on error
2093
;
2094
;---------------------------------------------------
2095
align 4
2096
SOCKET_ptr_to_num:
2097
 
3556 hidnplayr 2098
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2099
 
2100
        call    SOCKET_check
2101
        jz      .error
2102
 
2103
        mov     eax, [eax + SOCKET.Number]
2104
 
3556 hidnplayr 2105
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2106
        ret
2107
 
2108
  .error:
3556 hidnplayr 2109
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2110
        ret
2111
 
2112
 
2113
;---------------------------------------------------
2114
;
2115
; SOCKET_check
2116
;
2117
; checks if the given value is really a socket ptr
2118
;
2119
; IN:  eax = socket ptr
2120
; OUT: eax = 0 on error, unchanged otherwise
2121
;       ZF = set on error
2122
;
2123
;---------------------------------------------------
2124
align 4
2125
SOCKET_check:
2126
 
3556 hidnplayr 2127
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2128
 
2129
        push    ebx
2130
        mov     ebx, net_sockets
2131
 
2132
  .next_socket:
2133
        mov     ebx, [ebx + SOCKET.NextPtr]
2134
        or      ebx, ebx
2135
        jz      .done
2136
        cmp     ebx, eax
2137
        jnz     .next_socket
2138
 
2139
  .done:
2140
        mov     eax, ebx
2141
        test    eax, eax
2142
        pop     ebx
2143
 
2144
        ret
2145
 
2146
 
2147
 
2148
;---------------------------------------------------
2149
;
2150
; SOCKET_check_owner
2151
;
2152
; checks if the caller application owns the socket
2153
;
2154
; IN:  eax = socket ptr
2155
; OUT:  ZF = true/false
2156
;
2157
;---------------------------------------------------
2158
align 4
2159
SOCKET_check_owner:
2160
 
3556 hidnplayr 2161
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2162
 
2163
        push    ebx
2164
        mov     ebx, [TASK_BASE]
2165
        mov     ebx, [ebx + TASKDATA.pid]
2166
        cmp     [eax + SOCKET.PID], ebx
2167
        pop      ebx
2168
 
2169
        ret
2170
 
2171
 
2172
 
2173
 
2174
;------------------------------------------------------
2175
;
2176
; SOCKET_process_end
2177
;
2178
; Kernel calls this function when a certain process ends
2179
; This function will check if the process had any open sockets
2180
; And update them accordingly
2181
;
2182
; IN:  edx = pid
2183
; OUT: /
2184
;
2185
;------------------------------------------------------
2186
align 4
2187
SOCKET_process_end:
2188
 
3648 hidnplayr 2189
        pushf
2190
        cli     ; FIXME
2191
 
3556 hidnplayr 2192
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2193
 
3647 hidnplayr 2194
        pusha
2195
        mov     ecx, socket_mutex
2196
        call    mutex_lock
2197
        popa
2198
 
3545 hidnplayr 2199
        push    ebx
2200
        mov     ebx, net_sockets
2201
 
2202
  .next_socket:
2203
        mov     ebx, [ebx + SOCKET.NextPtr]
2204
  .next_socket_test:
2205
        test    ebx, ebx
2206
        jz      .done
2207
 
2208
        cmp     [ebx + SOCKET.PID], edx
2209
        jne     .next_socket
2210
 
3556 hidnplayr 2211
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2212
 
2213
        mov     [ebx + SOCKET.PID], 0
2214
        mov     eax, ebx
2215
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2216
 
3545 hidnplayr 2217
        pusha
3648 hidnplayr 2218
        mov     ecx, socket_mutex
2219
        call    mutex_unlock
2220
        popa
2221
 
2222
        pusha
3652 hidnplayr 2223
        cmp     [eax + SOCKET.Domain], AF_INET4
2224
        jne     .free
2225
 
2226
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2227
        jne     .free
2228
 
2229
        call    TCP_close
2230
        jmp     .closed
2231
 
2232
  .free:
2233
        call    SOCKET_free
2234
 
2235
  .closed:
3545 hidnplayr 2236
        popa
3648 hidnplayr 2237
 
2238
        pusha
2239
        mov     ecx, socket_mutex
2240
        call    mutex_lock
2241
        popa
2242
 
3545 hidnplayr 2243
        jmp     .next_socket_test
2244
 
2245
  .done:
2246
        pop     ebx
2247
 
3647 hidnplayr 2248
        pusha
2249
        mov     ecx, socket_mutex
2250
        call    mutex_unlock
2251
        popa
2252
 
3648 hidnplayr 2253
        popf
2254
 
3545 hidnplayr 2255
        ret
2256
 
2257
 
2258
 
2259
 
2260
;-----------------------------------------------------------------
2261
;
2262
; SOCKET_is_connecting
2263
;
2264
;  IN:  eax = socket ptr
2265
;  OUT: /
2266
;
2267
;-----------------------------------------------------------------
2268
 
2269
align 4
2270
SOCKET_is_connecting:
2271
 
3556 hidnplayr 2272
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2273
 
2274
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2275
        or      [eax + SOCKET.options], SS_ISCONNECTING
2276
 
2277
        jmp     SOCKET_notify
2278
 
2279
 
2280
 
2281
;-----------------------------------------------------------------
2282
;
2283
; SOCKET_is_connected
2284
;
2285
;  IN:  eax = socket ptr
2286
;  OUT: /
2287
;
2288
;-----------------------------------------------------------------
2289
 
2290
align 4
2291
SOCKET_is_connected:
2292
 
3556 hidnplayr 2293
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2294
 
2295
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2296
        or      [eax + SOCKET.options], SS_ISCONNECTED
2297
 
2298
        jmp     SOCKET_notify
2299
 
2300
 
2301
 
2302
 
2303
;-----------------------------------------------------------------
2304
;
2305
; SOCKET_is_disconnecting
2306
;
2307
;  IN:  eax = socket ptr
2308
;  OUT: /
2309
;
2310
;-----------------------------------------------------------------
2311
 
2312
align 4
2313
SOCKET_is_disconnecting:
2314
 
3556 hidnplayr 2315
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2316
 
2317
        and     [eax + SOCKET.options], not (SS_ISCONNECTING)
2318
        or      [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
2319
 
2320
        jmp     SOCKET_notify
2321
 
2322
 
2323
 
2324
;-----------------------------------------------------------------
2325
;
2326
; SOCKET_is_disconnected
2327
;
2328
;  IN:  eax = socket ptr
2329
;  OUT: /
2330
;
2331
;-----------------------------------------------------------------
2332
 
2333
align 4
2334
SOCKET_is_disconnected:
2335
 
3556 hidnplayr 2336
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2337
 
2338
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2339
        or      [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
2340
 
2341
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2342
        je      .tcp
2343
 
2344
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
2345
        je      .udp
2346
 
2347
        jmp     SOCKET_notify
2348
 
2349
  .tcp:
2350
  .udp:
2351
        mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
2352
        mov     [eax + UDP_SOCKET.RemotePort], 0
2353
 
2354
        jmp     SOCKET_notify
2355
 
2356
 
2357
;-----------------------------------------------------------------
2358
;
2359
; SOCKET_cant_recv_more
2360
;
2361
;  IN:  eax = socket ptr
2362
;  OUT: /
2363
;
2364
;-----------------------------------------------------------------
2365
 
2366
align 4
2367
SOCKET_cant_recv_more:
2368
 
3556 hidnplayr 2369
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2370
 
2371
        or      [eax + SOCKET.options], SS_CANTRCVMORE
2372
 
3565 hidnplayr 2373
        call    SOCKET_notify
2374
 
3545 hidnplayr 2375
        ret
2376
 
2377
 
2378
 
2379
;-----------------------------------------------------------------
2380
;
2381
; SOCKET_cant_send_more
2382
;
2383
;  IN:  eax = socket ptr
2384
;  OUT: /
2385
;
2386
;-----------------------------------------------------------------
2387
 
2388
align 4
2389
SOCKET_cant_send_more:
2390
 
3556 hidnplayr 2391
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2392
 
2393
        or      [eax + SOCKET.options], SS_CANTSENDMORE
3565 hidnplayr 2394
        mov     [eax + SOCKET.snd_proc], s_error
3545 hidnplayr 2395
 
3565 hidnplayr 2396
        call    SOCKET_notify
2397
 
3545 hidnplayr 2398
        ret