Subversion Repositories Kolibri OS

Rev

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