root/lang/c/librtmp/rtmp.c @ 35737

Revision 35737, 35.8 kB (checked in by itkz, 4 years ago)

fixed chunk size bug

Line 
1/*
2    SDL_archive
3    Copyright (C) 2004  Kazunori Itoyanagi
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with this library; if not, write to the Free
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19    ITOYANAGI Kazunori
20    kazunori@itoyanagi.name
21*/
22
23
24#ifdef MACOS_OPENTRANSPORT
25#include <OpenTransport.h>
26#include <OpenTptInternet.h>
27#else
28#if defined(__WIN32__) || defined(WIN32)
29#define __USE_W32_SOCKETS
30#include <windows.h>
31#ifdef __CYGWIN__
32#include <netinet/in.h>
33#endif
34#else /* UNIX */
35#ifdef __OS2__
36#include <types.h>
37#include <sys/ioctl.h>
38#endif
39#include <sys/time.h>
40#include <unistd.h>
41#include <fcntl.h>
42#include <netinet/in.h>
43#ifndef __BEOS__
44#include <arpa/inet.h>
45#endif
46#ifdef linux /* FIXME: what other platforms have this? */
47#include <netinet/tcp.h>
48#endif
49#include <netdb.h>
50#include <sys/socket.h>
51#endif /* WIN32 */
52#endif /* Open Transport */
53
54#if defined(__WIN32__) || defined(WIN32)
55#include <mmsystem.h>
56#endif
57
58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61#include <unistd.h>
62#include <time.h>
63#include <errno.h>
64
65
66#include "rtmp.h"
67#include "rtmp_packet.h"
68#include "amf_packet.h"
69#include "data_rw.h"
70
71
72static rtmp_server_client_t *get_new_server_client(rtmp_server_t *s);
73static int rtmp_server_client_set_will_send_buffer(
74    rtmp_server_client_t *rc, unsigned char *data, size_t size);
75static void rtmp_server_client_delete_received_buffer(
76    rtmp_server_client_t *rsc, size_t size);
77static rtmp_result_t rtmp_server_client_send_and_recv(
78    rtmp_server_client_t *rsc);
79static rtmp_result_t rtmp_server_client_send_packet(
80    rtmp_server_client_t *rsc, rtmp_packet_t *packet);
81static void rtmp_server_client_process_packet(
82    rtmp_server_client_t *rsc, rtmp_packet_t *packet);
83static void rtmp_server_client_free(
84    rtmp_server_t *rs, rtmp_server_client_t *rsc);
85
86static void rtmp_server_client_handshake_first(
87    rtmp_server_client_t *server_client);
88static void rtmp_server_client_handshake_second(
89    rtmp_server_client_t *server_client);
90static void rtmp_server_client_get_packet(
91    rtmp_server_client_t *server_client);
92
93
94rtmp_server_t *rtmp_server_create(unsigned short port_number)
95{
96    rtmp_server_t *rtmp_server;
97    int ret;
98
99    rtmp_server = (rtmp_server_t*)malloc(sizeof(rtmp_server_t));
100    if (rtmp_server == NULL) {
101        return NULL;
102    }
103    rtmp_server->client_pool = NULL;
104    rtmp_server->client_working = NULL;
105    rtmp_server->stand_by_socket = -1;
106
107    rtmp_server->conn_sock = socket(AF_INET, SOCK_STREAM, 0);
108    if (rtmp_server->conn_sock == -1) {
109        rtmp_server_free(rtmp_server);
110        return NULL;
111    }
112    rtmp_server->stand_by_socket = 1;
113
114    rtmp_server->conn_sockaddr.sin_family = AF_INET;
115    rtmp_server->conn_sockaddr.sin_addr.s_addr = INADDR_ANY;
116    rtmp_server->conn_sockaddr.sin_port = htons(port_number);
117    ret = bind(
118        rtmp_server->conn_sock,
119        (struct sockaddr*)&(rtmp_server->conn_sockaddr),
120        sizeof(rtmp_server->conn_sockaddr));
121    if (ret == -1) {
122        rtmp_server_free(rtmp_server);
123        return NULL;
124    }
125
126    ret = listen(rtmp_server->conn_sock, 10);
127    if (ret == -1) {
128        rtmp_server_free(rtmp_server);
129        return NULL;
130    }
131
132    return rtmp_server;
133}
134
135
136void rtmp_server_process_message(rtmp_server_t *rs)
137{
138    rtmp_server_client_t *rsc;
139    rtmp_server_client_t *next;
140    int client_sock;
141#ifdef __MINGW32__
142    int addrlen;
143#else
144    socklen_t addrlen;
145#endif
146    fd_set fdset;
147    int ret;
148    struct timeval timeout;
149    rtmp_result_t result;
150
151    FD_ZERO(&fdset);
152    FD_SET((unsigned int)rs->conn_sock, &fdset);
153    timeout.tv_sec = 0;
154    timeout.tv_usec = 0;
155    ret = select(rs->conn_sock + 1, &fdset, NULL, NULL, &timeout);
156    if (ret == 1) {
157        rsc = get_new_server_client(rs);
158
159        addrlen = sizeof(rs->conn_sockaddr);
160        client_sock = accept(
161            rs->conn_sock,
162            (struct sockaddr*)&(rs->conn_sockaddr),
163            &addrlen);
164        if (client_sock == -1) {
165            return;
166        }
167
168        rsc->conn_sock = client_sock;
169        rsc->prev = NULL;
170        rsc->next = rs->client_working;
171        if (rs->client_working == NULL) {
172            rs->client_working = rsc;
173        } else {
174            rs->client_working->prev = rsc;
175            rs->client_working = rsc;
176        }
177    }
178
179    rsc = rs->client_working;
180    while (rsc) {
181        result = rtmp_server_client_send_and_recv(rsc);
182        rsc->process_message(rsc);
183        if (result == RTMP_ERROR_DISCONNECTED) {
184#ifdef DEBUG
185printf("client disconnected\n");
186#endif
187            next = rsc->next;
188            rtmp_server_client_free(rs, rsc);
189            rsc = next;
190        } else {
191            rsc = rsc->next;
192        }
193    }
194}
195
196
197static rtmp_result_t rtmp_server_client_send_and_recv(rtmp_server_client_t *rsc)
198{
199    fd_set fdset;
200    int ret;
201    struct timeval timeout;
202    int received_size;
203    int sent_size;
204
205    FD_ZERO(&fdset);
206    FD_SET(rsc->conn_sock, &fdset);
207    timeout.tv_sec = 0;
208    timeout.tv_usec = 0;
209    ret = select(rsc->conn_sock + 1, &fdset, NULL, NULL, &timeout);
210    if (ret == 1) {
211        received_size = recv(
212            rsc->conn_sock,
213            (void*)(rsc->received_buffer + rsc->received_size),
214            RTMP_BUFFER_SIZE - rsc->received_size, 0);
215        if (received_size == -1) {
216            return RTMP_ERROR_DISCONNECTED;
217        }
218#ifdef DEBUG
219if (received_size > 0) {
220    printf("received: %d\n", received_size);
221}
222#endif
223        rsc->received_size += received_size;
224    }
225
226    rsc->process_message(rsc);
227
228    if (rsc->will_send_size > 0) {
229        FD_ZERO(&fdset);
230        FD_SET(rsc->conn_sock, &fdset);
231        timeout.tv_sec = 0;
232        timeout.tv_usec = 0;
233        ret = select(rsc->conn_sock + 1, NULL, &fdset, NULL, &timeout);
234        if (ret == 1) {
235            sent_size = send(
236                rsc->conn_sock,
237                rsc->will_send_buffer,
238                rsc->will_send_size, 0);
239            if (sent_size == -1) {
240                return RTMP_ERROR_DISCONNECTED;
241            }
242#ifdef DEBUG
243if (sent_size > 0) {
244    printf("sent: %d\n", sent_size);
245}
246#endif
247            if (rsc->will_send_size - sent_size > 0) {
248                memmove(
249                    rsc->will_send_buffer,
250                    rsc->will_send_buffer + sent_size,
251                    rsc->will_send_size - sent_size);
252            }
253            rsc->will_send_size -= sent_size;
254        }
255    }
256
257    return RTMP_SUCCESS;
258}
259
260
261static rtmp_server_client_t *get_new_server_client(rtmp_server_t *rs)
262{
263    rtmp_server_client_t *rsc;
264
265    if (rs->client_pool == NULL) {
266        rsc = (rtmp_server_client_t*)malloc(sizeof(rtmp_server_client_t));
267        if (rsc == NULL) {
268            return NULL;
269        }
270    } else {
271        rsc = rs->client_pool;
272        rs->client_pool = rsc->next;
273        if (rs->client_pool) {
274            rs->client_pool->prev = NULL;
275        }
276    }
277
278
279    rsc->received_size = 0;
280    rsc->will_send_size = 0;
281    rsc->amf_chunk_size = DEFAULT_AMF_CHUNK_SIZE;
282    rsc->process_message = rtmp_server_client_handshake_first;
283
284    return rsc;
285}
286
287
288static int rtmp_server_client_set_will_send_buffer(
289    rtmp_server_client_t *rsc, unsigned char *data, size_t size)
290{
291    if (rsc->will_send_size + size > RTMP_BUFFER_SIZE) {
292        return RTMP_ERROR_BUFFER_OVERFLOW;
293    }
294    memmove(
295        rsc->will_send_buffer + rsc->will_send_size,
296        data, size);
297    rsc->will_send_size += size;
298    return RTMP_SUCCESS;
299}
300
301
302static void rtmp_server_client_delete_received_buffer(
303    rtmp_server_client_t *rsc, size_t size)
304{
305    if (size >= rsc->received_size) {
306        rsc->received_size = 0;
307    } else {
308        memmove(
309            rsc->received_buffer,
310            rsc->received_buffer + size,
311            rsc->received_size - size);
312        rsc->received_size -= size;
313    }
314}
315
316
317void rtmp_server_client_handshake_first(rtmp_server_client_t *rsc)
318{
319    unsigned char magic[] = {0x03};
320    int i;
321#if defined(__WIN32__) || defined(WIN32)
322    DWORD now;
323#else
324    unsigned long now;
325#endif
326
327    if (rsc->received_size >= (1 + RTMP_HANDSHAKE_SIZE)) {
328        rtmp_server_client_set_will_send_buffer(
329            rsc, magic, 1);
330#if defined(__WIN32__) || defined(WIN32)
331        now = timeGetTime();
332#else
333        now = time(NULL) * 1000;
334#endif
335        write_le32int(rsc->handshake, (int)now);
336        write_le32int(rsc->handshake + 4, 0);
337        for (i = 8; i < RTMP_HANDSHAKE_SIZE; ++i) {
338            rsc->handshake[i] = (unsigned char)(rand() % 256);
339        }
340        rtmp_server_client_set_will_send_buffer(
341            rsc,
342            rsc->handshake,
343            RTMP_HANDSHAKE_SIZE);
344        rtmp_server_client_set_will_send_buffer(
345            rsc,
346            rsc->received_buffer + 1,
347            RTMP_HANDSHAKE_SIZE);
348        rtmp_server_client_delete_received_buffer(
349            rsc,
350            1 + RTMP_HANDSHAKE_SIZE);
351#ifdef DEBUG
352printf("handshake 1\n");
353#endif
354        rsc->process_message = rtmp_server_client_handshake_second;
355    }
356}
357
358
359void rtmp_server_client_handshake_second(rtmp_server_client_t *rsc)
360{
361    unsigned char *client_signature;
362    unsigned char *response;
363
364    if (rsc->received_size >= RTMP_HANDSHAKE_SIZE) {
365        client_signature = rsc->received_buffer;
366        response = rsc->received_buffer;
367#ifdef DEBUG
368        if (memcmp(rsc->handshake, response, RTMP_HANDSHAKE_SIZE) == 0) {
369            printf("handshake response OK!\n");
370        }
371#endif
372        rtmp_server_client_delete_received_buffer(
373            rsc, RTMP_HANDSHAKE_SIZE);
374#ifdef DEBUG
375printf("handshake 2\n");
376#endif
377        rsc->data = rtmp_packet_create();
378        rsc->process_message = rtmp_server_client_get_packet;
379        rtmp_server_client_send_server_bandwidth(rsc);
380        rtmp_server_client_send_client_bandwidth(rsc);
381        rtmp_server_client_send_ping(rsc);
382    }
383}
384
385
386static void rtmp_server_client_process_packet(
387    rtmp_server_client_t *rsc, rtmp_packet_t *packet)
388{
389    rtmp_packet_inner_amf_t *inner_amf;
390    amf_packet_t *amf;
391    char *command;
392    double number;
393    char *code;
394    char *level;
395
396    switch (packet->data_type) {
397    case RTMP_DATATYPE_CHUNK_SIZE:
398        break;
399    case RTMP_DATATYPE_BYTES_READ:
400        break;
401    case RTMP_DATATYPE_PING:
402        break;
403    case RTMP_DATATYPE_SERVER_BW:
404        break;
405    case RTMP_DATATYPE_CLIENT_BW:
406        break;
407    case RTMP_DATATYPE_AUDIO_DATA:
408        break;
409    case RTMP_DATATYPE_VIDEO_DATA:
410        break;
411    case RTMP_DATATYPE_MESSAGE:
412        break;
413    case RTMP_DATATYPE_NOTIFY:
414        inner_amf = packet->inner_amf_packets;
415        amf = inner_amf->amf;
416        if (amf->datatype != AMF_DATATYPE_STRING) {
417            break;
418        }
419        command = amf->string.value;
420#ifdef DEBUG
421        printf("notify command: %s\n", command);
422#endif
423        rtmp_packet_retrieve_status_info(packet, &code, &level);
424        if (code == NULL || level == NULL) {
425            break;
426        }
427#ifdef DEBUG
428        printf("code: %s\n", code);
429        printf("level: %s\n", level);
430#endif
431        /* FIXME: add event */
432        break;
433    case RTMP_DATATYPE_SHARED_OBJECT:
434        break;
435    case RTMP_DATATYPE_INVOKE:
436        inner_amf = packet->inner_amf_packets;
437        amf = inner_amf->amf;
438        if (amf->datatype != AMF_DATATYPE_STRING) {
439            break;
440        }
441        command = amf->string.value;
442        amf = inner_amf->next->amf;
443        if (amf->datatype != AMF_DATATYPE_NUMBER) {
444            break;
445        }
446        number = amf->number.value;
447#ifdef DEBUG
448        printf("invoke command: %s\n", command);
449#endif
450        if (strcmp(command, "_result") == 0) {
451            rtmp_packet_retrieve_status_info(packet, &code, &level);
452            if (code == NULL || level == NULL) {
453                break;
454            }
455#ifdef DEBUG
456            printf("code: %s\n", code);
457            printf("level: %s\n", level);
458#endif
459            /* FIXME: add event */
460        } else if (strcmp(command, "connect") == 0) {
461//            rsc->amf_chunk_size = 4096;
462            rtmp_server_client_send_chunk_size(rsc);
463            rtmp_server_client_send_connect_result(rsc, number);
464        } else if (strcmp(command, "createStream") == 0) {
465            rtmp_server_client_send_create_stream_result(rsc, number);
466        } else if (strcmp(command, "play") == 0) {
467            rtmp_server_client_send_play_result_success(rsc, number);
468        }
469        break;
470    default:
471        break;
472    }
473}
474
475
476static rtmp_result_t rtmp_server_client_send_packet(
477    rtmp_server_client_t *rsc, rtmp_packet_t *packet)
478{
479    rtmp_result_t result;
480    size_t packet_size;
481
482    unsigned char fuck[1024];
483    result = rtmp_packet_serialize(
484        packet,
485        fuck,
486        1024,
487        rsc->amf_chunk_size,
488        &packet_size);
489    if (result == RTMP_SUCCESS) {
490        rtmp_server_client_set_will_send_buffer(
491            rsc, fuck, packet_size);
492    }
493
494    return RTMP_SUCCESS;
495}
496
497
498void rtmp_server_client_send_server_bandwidth(
499    rtmp_server_client_t *rsc)
500{
501    rtmp_packet_t *rtmp_packet;
502
503    rtmp_packet = (rtmp_packet_t*)rsc->data;
504    rtmp_packet_cleanup(rtmp_packet);
505    rtmp_packet->object_id = 2;
506    rtmp_packet->timer = 0;
507    rtmp_packet->data_type = RTMP_DATATYPE_SERVER_BW;
508    rtmp_packet->stream_id = 0;
509    rtmp_packet->body_type = RTMP_BODY_TYPE_DATA;
510    rtmp_packet_allocate_body_data(rtmp_packet, 4);
511    rtmp_packet->body_data[0] = 0x00;
512    rtmp_packet->body_data[1] = 0x26;
513    rtmp_packet->body_data[2] = 0x25;
514    rtmp_packet->body_data[3] = 0xA0;
515
516    rtmp_server_client_send_packet(rsc, rtmp_packet);
517}
518
519
520void rtmp_server_client_send_client_bandwidth(
521    rtmp_server_client_t *rsc)
522{
523    rtmp_packet_t *rtmp_packet;
524
525    rtmp_packet = (rtmp_packet_t*)rsc->data;
526    rtmp_packet_cleanup(rtmp_packet);
527    rtmp_packet->object_id = 2;
528    rtmp_packet->timer = 0;
529    rtmp_packet->data_type = RTMP_DATATYPE_CLIENT_BW;
530    rtmp_packet->stream_id = 0;
531    rtmp_packet->body_type = RTMP_BODY_TYPE_DATA;
532    rtmp_packet_allocate_body_data(rtmp_packet, 5);
533    rtmp_packet->body_data[0] = 0x00;
534    rtmp_packet->body_data[1] = 0x26;
535    rtmp_packet->body_data[2] = 0x25;
536    rtmp_packet->body_data[3] = 0xA0;
537    rtmp_packet->body_data[4] = 0x02;
538
539    rtmp_server_client_send_packet(rsc, rtmp_packet);
540}
541
542
543void rtmp_server_client_send_ping(rtmp_server_client_t *rsc)
544{
545    rtmp_packet_t *rtmp_packet;
546
547    rtmp_packet = (rtmp_packet_t*)rsc->data;
548    rtmp_packet_cleanup(rtmp_packet);
549    rtmp_packet->object_id = 2;
550    rtmp_packet->timer = 0;
551    rtmp_packet->data_type = RTMP_DATATYPE_PING;
552    rtmp_packet->stream_id = 0;
553    rtmp_packet->body_type = RTMP_BODY_TYPE_DATA;
554    rtmp_packet_allocate_body_data(rtmp_packet, 6);
555    rtmp_packet->body_data[0] = 0x00;
556    rtmp_packet->body_data[1] = 0x00;
557    rtmp_packet->body_data[2] = 0x00;
558    rtmp_packet->body_data[3] = 0x00;
559    rtmp_packet->body_data[4] = 0x00;
560    rtmp_packet->body_data[5] = 0x00;
561
562    rtmp_server_client_send_packet(rsc, rtmp_packet);
563}
564
565
566void rtmp_server_client_send_chunk_size(
567    rtmp_server_client_t *rsc)
568{
569    rtmp_packet_t *rtmp_packet;
570
571    rtmp_packet = (rtmp_packet_t*)rsc->data;
572    rtmp_packet_cleanup(rtmp_packet);
573    rtmp_packet->object_id = 2;
574    rtmp_packet->timer = 0;
575    rtmp_packet->data_type = RTMP_DATATYPE_PING;
576    rtmp_packet->stream_id = 0;
577    rtmp_packet->body_type = RTMP_BODY_TYPE_DATA;
578    rtmp_packet_allocate_body_data(rtmp_packet, 4);
579    write_be32int(rtmp_packet->body_data, rsc->amf_chunk_size);
580
581    rtmp_server_client_send_packet(rsc, rtmp_packet);
582}
583
584
585void rtmp_server_client_send_connect_result(
586    rtmp_server_client_t *rsc, double number)
587{
588    rtmp_packet_t *rtmp_packet;
589    amf_packet_t *amf_object;
590
591    rtmp_packet = (rtmp_packet_t*)rsc->data;
592    rtmp_packet_cleanup(rtmp_packet);
593    rtmp_packet->object_id = 3;
594    rtmp_packet->timer = 0;
595    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
596    rtmp_packet->stream_id = 0;
597    rtmp_packet->body_type = RTMP_BODY_TYPE_AMF;
598
599    rtmp_packet_add_amf(
600        rtmp_packet,
601        amf_packet_create_string("_result"));
602    rtmp_packet_add_amf(
603        rtmp_packet,
604        amf_packet_create_number(number));
605
606    amf_object = amf_packet_create_object();
607    amf_packet_add_property_to_object(
608        amf_object, "fmsver", amf_packet_create_string("librtmp 0.1"));
609    amf_packet_add_property_to_object(
610        amf_object, "capabilities", amf_packet_create_number(31));
611    rtmp_packet_add_amf(rtmp_packet, amf_object);
612
613    amf_object = amf_packet_create_object();
614    amf_packet_add_property_to_object(
615        amf_object, "level", amf_packet_create_string("status"));
616    amf_packet_add_property_to_object(
617        amf_object, "code", amf_packet_create_string("NetConnection.Connect.Success"));
618    amf_packet_add_property_to_object(
619        amf_object, "description", amf_packet_create_string("Connection succeeded."));
620    amf_packet_add_property_to_object(
621        amf_object, "clientid", amf_packet_create_number(313639155));
622    /* FIXME: increment client id */
623    amf_packet_add_property_to_object(
624        amf_object, "objectEncoding", amf_packet_create_number(0));
625    rtmp_packet_add_amf(rtmp_packet, amf_object);
626
627    rtmp_server_client_send_packet(rsc, rtmp_packet);
628}
629
630
631void rtmp_server_client_send_create_stream_result(
632    rtmp_server_client_t *rsc, double number)
633{
634    rtmp_packet_t *rtmp_packet;
635
636    rtmp_packet = (rtmp_packet_t*)rsc->data;
637    rtmp_packet_cleanup(rtmp_packet);
638    rtmp_packet->object_id = 3;
639    rtmp_packet->timer = 0;
640    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
641    rtmp_packet->stream_id = 0;
642    rtmp_packet->body_type = RTMP_BODY_TYPE_AMF;
643
644    rtmp_packet_add_amf(
645        rtmp_packet,
646        amf_packet_create_string("_result"));
647    rtmp_packet_add_amf(
648        rtmp_packet,
649        amf_packet_create_number(number));
650    rtmp_packet_add_amf(
651        rtmp_packet,
652        amf_packet_create_null());
653    rtmp_packet_add_amf(
654        rtmp_packet,
655        amf_packet_create_number(15125));
656    /* FIXME: What's this number */
657
658    rtmp_server_client_send_packet(rsc, rtmp_packet);
659}
660
661
662void rtmp_server_client_send_play_result_success(
663    rtmp_server_client_t *rsc, double number)
664{
665    rtmp_packet_t *rtmp_packet;
666    amf_packet_t *amf_object;
667
668    rtmp_packet = (rtmp_packet_t*)rsc->data;
669    rtmp_packet_cleanup(rtmp_packet);
670    rtmp_packet->object_id = 5;
671    rtmp_packet->timer = 0;
672    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
673    rtmp_packet->stream_id = 1; /* FIXME */
674    rtmp_packet->body_type = RTMP_BODY_TYPE_AMF;
675
676    rtmp_packet_add_amf(
677        rtmp_packet,
678        amf_packet_create_string("onStatus"));
679    rtmp_packet_add_amf(
680        rtmp_packet,
681        amf_packet_create_number(number));
682    rtmp_packet_add_amf(
683        rtmp_packet,
684        amf_packet_create_null());
685
686    amf_object = amf_packet_create_object();
687    amf_packet_add_property_to_object(
688        amf_object, "code", amf_packet_create_string("NetStream.Play.Start"));
689    amf_packet_add_property_to_object(
690        amf_object, "level", amf_packet_create_string("status"));
691    amf_packet_add_property_to_object(
692        amf_object, "description", amf_packet_create_string(""));
693    rtmp_packet_add_amf(rtmp_packet, amf_object);
694
695    rtmp_server_client_send_packet(rsc, rtmp_packet);
696}
697
698
699void rtmp_server_client_send_play_result_error(
700    rtmp_server_client_t *rsc, double number)
701{
702    rtmp_packet_t *rtmp_packet;
703    amf_packet_t *amf_object;
704
705    rtmp_packet = (rtmp_packet_t*)rsc->data;
706    rtmp_packet_cleanup(rtmp_packet);
707    rtmp_packet->object_id = 3;
708    rtmp_packet->timer = 0;
709    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
710    rtmp_packet->stream_id = 0; /* FIXME: 8byte header */
711    rtmp_packet->body_type = RTMP_BODY_TYPE_AMF;
712
713    rtmp_packet_add_amf(
714        rtmp_packet,
715        amf_packet_create_string("onStatus"));
716    rtmp_packet_add_amf(
717        rtmp_packet,
718        amf_packet_create_number(number));
719    rtmp_packet_add_amf(
720        rtmp_packet,
721        amf_packet_create_null());
722/* Flash Player crashes when this code is available
723    rtmp_packet_add_amf(
724        rtmp_packet,
725        amf_packet_create_number(15125));
726*/
727
728    amf_object = amf_packet_create_object();
729    amf_packet_add_property_to_object(
730        amf_object, "level", amf_packet_create_string("error"));
731    amf_packet_add_property_to_object(
732        amf_object, "code", amf_packet_create_string("NetStream.Play.StreamNotFound"));
733    amf_packet_add_property_to_object(
734        amf_object, "description", amf_packet_create_string("Failed to play test.mp4; stream not found."));
735    amf_packet_add_property_to_object(
736        amf_object, "clientid", amf_packet_create_number(313639155));
737    /* FIXME: increment client id */
738    amf_packet_add_property_to_object(
739        amf_object, "details", amf_packet_create_string("test.mp4"));
740    rtmp_packet_add_amf(rtmp_packet, amf_object);
741
742    rtmp_server_client_send_packet(rsc, rtmp_packet);
743}
744
745
746static void rtmp_server_client_get_packet(rtmp_server_client_t *rsc)
747{
748    rtmp_result_t ret;
749    size_t packet_size;
750    rtmp_packet_t *packet;
751
752    packet = (rtmp_packet_t*)rsc->data;
753    ret = rtmp_packet_analyze_data(
754        packet,
755        rsc->received_buffer, rsc->received_size,
756        rsc->amf_chunk_size,
757        &packet_size);
758    if (ret == RTMP_SUCCESS) {
759        rtmp_server_client_delete_received_buffer(rsc, packet_size);
760        rtmp_server_client_process_packet(rsc, packet);
761    }
762}
763
764
765static void rtmp_server_client_free(rtmp_server_t *rs, rtmp_server_client_t *rsc)
766{
767    if (rsc->prev) {
768        rsc->prev->next = rsc->next;
769    } else {
770        rs->client_working = rsc->next;
771        if (rsc->next) {
772            rsc->next->prev = NULL;
773        }
774    }
775    if (rsc->next) {
776        rsc->next->prev = rsc->prev;
777    } else {
778        if (rsc->prev) {
779            rsc->prev->next = NULL;
780        }
781    }
782    if (rsc->data) {
783        rtmp_packet_free((rtmp_packet_t*)rsc->data);
784    }
785#ifdef __USE_W32_SOCKETS
786        closesocket(rsc->conn_sock);
787        WSACleanup();
788#else
789        close(rsc->conn_sock);
790#endif
791    free(rsc);
792}
793
794
795void rtmp_server_free(rtmp_server_t *rs)
796{
797    rtmp_server_client_t *rsc;
798    rtmp_server_client_t *next;
799
800    rsc = rs->client_working;
801    while (rsc) {
802        next = rsc->next;
803        rtmp_server_client_free(rs, rsc);
804        rsc = next;
805    }
806    rsc = rs->client_pool;
807    while (rsc) {
808        free(rsc);
809    }
810    if (rs->stand_by_socket) {
811#ifdef __USE_W32_SOCKETS
812        closesocket(rs->conn_sock);
813        WSACleanup();
814#else
815        close(rs->conn_sock);
816#endif
817    }
818    free(rs);
819}
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834static void rtmp_client_handshake_first(rtmp_client_t *rc);
835static void rtmp_client_handshake_second(rtmp_client_t *rc);
836static void rtmp_client_get_packet(rtmp_client_t *rc);
837static void rtmp_client_process_packet(
838    rtmp_client_t *rc, rtmp_packet_t *packet);
839
840static int rtmp_client_set_will_send_buffer(
841    rtmp_client_t *rc, unsigned char *data, size_t size);
842static void rtmp_client_delete_received_buffer(
843    rtmp_client_t *rc, size_t size);
844static rtmp_result_t rtmp_client_send_packet(
845    rtmp_client_t *rc, rtmp_packet_t *packet);
846static rtmp_result_t rtmp_client_add_event(
847    rtmp_client_t *rc, char *code, char *level);
848
849
850rtmp_client_t *rtmp_client_create(const char *host, unsigned short port_number)
851{
852    rtmp_client_t *rc;
853    int ret;
854#ifdef __USE_W32_SOCKETS
855    WSADATA data;
856#endif
857    struct sockaddr_in conn_sockaddr;
858
859#ifdef __USE_W32_SOCKETS
860    WSAStartup(MAKEWORD(2, 0), &data);
861#endif
862
863    srand((unsigned)time(NULL));
864
865    rc = (rtmp_client_t*)malloc(sizeof(rtmp_client_t));
866    if (rc == NULL) {
867        return NULL;
868    }
869
870    memset(&conn_sockaddr, 0, sizeof(conn_sockaddr));
871    conn_sockaddr.sin_family = AF_INET;
872    conn_sockaddr.sin_port = htons(port_number);
873    conn_sockaddr.sin_addr.s_addr = inet_addr(host);
874    if (conn_sockaddr.sin_addr.s_addr == INADDR_NONE) {
875        free(rc);
876        return NULL;
877    }
878
879    rc->conn_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
880    if (rc->conn_sock == -1) {
881        free(rc);
882        return NULL;
883    }
884
885#ifdef __USE_W32_SOCKETS
886    ret = connect(
887        rc->conn_sock,
888        (PSOCKADDR)&conn_sockaddr, sizeof(conn_sockaddr));
889    if (ret == SOCKET_ERROR) {
890        free(rc);
891        return NULL;
892    }
893#else
894    ret = connect(
895        rc->conn_sock, (const struct sockaddr*)&(conn_sockaddr),
896        sizeof(conn_sockaddr));
897    if (ret == -1) {
898        free(rc);
899        return NULL;
900    }
901#endif
902
903    rc->amf_chunk_size = DEFAULT_AMF_CHUNK_SIZE;
904    rc->received_size = 0;
905    rc->will_send_size = 0;
906    rc->process_message = rtmp_client_handshake_first;
907    rc->message_number = 0.0;
908    rc->events = NULL;
909
910    return rc;
911}
912
913
914void rtmp_client_free(rtmp_client_t *rc)
915{
916    /* FIXME: clean up some memory */
917#ifdef __USE_W32_SOCKETS
918    closesocket(rc->conn_sock);
919    WSACleanup();
920#else
921    close(rc->conn_sock);
922#endif
923}
924
925
926void rtmp_client_process_message(rtmp_client_t *rc)
927{
928    fd_set fdset;
929    int ret;
930    int received_size;
931    int sent_size;
932    struct timeval timeout;
933
934    FD_ZERO(&fdset);
935    FD_SET(rc->conn_sock, &fdset);
936    timeout.tv_sec = 0;
937    timeout.tv_usec = 0;
938    ret = select(rc->conn_sock + 1, &fdset, NULL, NULL, &timeout);
939    if (ret == 1) {
940        received_size = recv(
941            rc->conn_sock,
942            rc->received_buffer + rc->received_size,
943            RTMP_BUFFER_SIZE - rc->received_size, 0);
944        /* FIXME: process finishing when recv returns -1 */
945        if (received_size > 0) {
946#ifdef DEBUG
947            printf("received: %d\n", received_size);
948#endif
949            rc->received_size += received_size;
950        }
951    }
952
953    rc->process_message(rc);
954
955    if (rc->will_send_size > 0) {
956        FD_ZERO(&fdset);
957        FD_SET(rc->conn_sock, &fdset);
958        timeout.tv_sec = 0;
959        timeout.tv_usec = 0;
960        ret = select(rc->conn_sock + 1, NULL, &fdset, NULL, &timeout);
961        if (ret == 1) {
962            sent_size = send(
963                rc->conn_sock,
964                rc->will_send_buffer,
965                rc->will_send_size, 0);
966#ifdef DEBUG
967            if (sent_size > 0) {
968                printf("sent: %d\n", sent_size);
969            }
970#endif
971            if (sent_size != -1) {
972                if (rc->will_send_size - sent_size > 0) {
973                    memmove(
974                        rc->will_send_buffer,
975                        rc->will_send_buffer + sent_size,
976                        rc->will_send_size - sent_size);
977                }
978                rc->will_send_size -= sent_size;
979            }
980        }
981    }
982}
983
984
985static int rtmp_client_set_will_send_buffer(
986    rtmp_client_t *rc, unsigned char *data, size_t size)
987{
988    if (rc->will_send_size + size > RTMP_BUFFER_SIZE) {
989        return RTMP_ERROR_BUFFER_OVERFLOW;
990    }
991    memmove(
992        rc->will_send_buffer + rc->will_send_size,
993        data, size);
994    rc->will_send_size += size;
995    return RTMP_SUCCESS;
996}
997
998
999static void rtmp_client_delete_received_buffer(
1000    rtmp_client_t *rc, size_t size)
1001{
1002    if (size >= rc->received_size) {
1003        rc->received_size = 0;
1004    } else {
1005        memmove(
1006            rc->received_buffer,
1007            rc->received_buffer + size,
1008            rc->received_size - size);
1009        rc->received_size -= size;
1010    }
1011}
1012
1013
1014static void rtmp_client_handshake_first(rtmp_client_t *rc)
1015{
1016    unsigned char magic[] = {0x03};
1017    int i;
1018#if defined(__WIN32__) || defined(WIN32)
1019    DWORD now;
1020#else
1021    unsigned long now;
1022#endif
1023
1024    rtmp_client_set_will_send_buffer(rc, magic, 1);
1025
1026#if defined(__WIN32__) || defined(WIN32)
1027    now = timeGetTime();
1028#else
1029    now = time(NULL) * 1000;
1030#endif
1031    write_le32int(rc->handshake, (int)now);
1032    write_le32int(rc->handshake + 4, 0);
1033    for (i = 8; i < RTMP_HANDSHAKE_SIZE; ++i) {
1034        rc->handshake[i] = (unsigned char)(rand() % 256);
1035    }
1036    rtmp_client_set_will_send_buffer(
1037        rc, rc->handshake, RTMP_HANDSHAKE_SIZE);
1038#ifdef DEBUG
1039printf("handshake 1\n");
1040#endif
1041    rc->process_message = rtmp_client_handshake_second;
1042}
1043
1044
1045static void rtmp_client_handshake_second(rtmp_client_t *rc)
1046{
1047    unsigned char *server_signature;
1048    unsigned char *response;
1049
1050    if (rc->received_size >= (1 + RTMP_HANDSHAKE_SIZE * 2)) {
1051        server_signature = rc->received_buffer + 1;
1052        response = rc->received_buffer + 1 + RTMP_HANDSHAKE_SIZE;
1053        rtmp_client_set_will_send_buffer(
1054            rc, server_signature, RTMP_HANDSHAKE_SIZE);
1055#ifdef DEBUG
1056        if (memcmp(rc->handshake, response, RTMP_HANDSHAKE_SIZE) == 0) {
1057            printf("handshake response OK!\n");
1058        }
1059#endif
1060        rtmp_client_delete_received_buffer(
1061            rc, 1 + RTMP_HANDSHAKE_SIZE * 2);
1062#ifdef DEBUG
1063printf("handshake 2\n");
1064#endif
1065        rc->data = rtmp_packet_create();
1066        rc->process_message = rtmp_client_get_packet;
1067        rtmp_client_connect(rc);
1068    }
1069}
1070
1071
1072static void rtmp_client_get_packet(rtmp_client_t *rc)
1073{
1074    rtmp_result_t ret;
1075    size_t packet_size;
1076    rtmp_packet_t *packet;
1077
1078    packet = (rtmp_packet_t*)rc->data;
1079    ret = rtmp_packet_analyze_data(
1080        packet,
1081        rc->received_buffer, rc->received_size,
1082        rc->amf_chunk_size,
1083        &packet_size);
1084    if (ret == RTMP_SUCCESS) {
1085        rtmp_client_delete_received_buffer(rc, packet_size);
1086        rtmp_client_process_packet(rc, packet);
1087    }
1088}
1089
1090
1091void rtmp_client_process_packet(
1092    rtmp_client_t *rc, rtmp_packet_t *packet)
1093{
1094    rtmp_packet_inner_amf_t *inner_amf;
1095    amf_packet_t *amf;
1096    char *command;
1097    char *code;
1098    char *level;
1099
1100    switch (packet->data_type) {
1101    case RTMP_DATATYPE_CHUNK_SIZE:
1102        rc->amf_chunk_size = read_be32int(packet->body_data);
1103        break;
1104    case RTMP_DATATYPE_BYTES_READ:
1105        break;
1106    case RTMP_DATATYPE_PING:
1107        break;
1108    case RTMP_DATATYPE_SERVER_BW:
1109        break;
1110    case RTMP_DATATYPE_CLIENT_BW:
1111        break;
1112    case RTMP_DATATYPE_AUDIO_DATA:
1113        break;
1114    case RTMP_DATATYPE_VIDEO_DATA:
1115        break;
1116    case RTMP_DATATYPE_MESSAGE:
1117        break;
1118    case RTMP_DATATYPE_NOTIFY:
1119        inner_amf = packet->inner_amf_packets;
1120        amf = inner_amf->amf;
1121        if (amf->datatype != AMF_DATATYPE_STRING) {
1122            break;
1123        }
1124        command = amf->string.value;
1125#ifdef DEBUG
1126        printf("command: %s\n", command);
1127#endif
1128        rtmp_packet_retrieve_status_info(packet, &code, &level);
1129        if (code == NULL || level == NULL) {
1130            break;
1131        }
1132#ifdef DEBUG
1133        printf("code: %s\n", code);
1134        printf("level: %s\n", level);
1135#endif
1136        rtmp_client_add_event(rc, code, level);
1137        break;
1138    case RTMP_DATATYPE_SHARED_OBJECT:
1139        break;
1140    case RTMP_DATATYPE_INVOKE:
1141        inner_amf = packet->inner_amf_packets;
1142        amf = inner_amf->amf;
1143        if (amf->datatype != AMF_DATATYPE_STRING) {
1144            break;
1145        }
1146        command = amf->string.value;
1147#ifdef DEBUG
1148        printf("command: %s\n", command);
1149#endif
1150        if (strcmp(command, "_result") == 0) {
1151            rtmp_packet_retrieve_status_info(packet, &code, &level);
1152            if (code == NULL || level == NULL) {
1153                break;
1154            }
1155#ifdef DEBUG
1156            printf("code: %s\n", code);
1157            printf("level: %s\n", level);
1158#endif
1159            rtmp_client_add_event(rc, code, level);
1160        }
1161        break;
1162    default:
1163        break;
1164    }
1165}
1166
1167
1168rtmp_result_t rtmp_client_add_event(
1169    rtmp_client_t *rc, char *code, char *level)
1170{
1171    rtmp_event_t *event;
1172    rtmp_event_t *last_event;
1173
1174    event = (rtmp_event_t*)malloc(sizeof(rtmp_event_t));
1175    event->code = (char*)malloc(strlen(code) + 1);
1176    strcpy(event->code, code);
1177    event->level = (char*)malloc(strlen(level) + 1);
1178    strcpy(event->level, level);
1179    event->next = NULL;
1180    if (rc->events == NULL) {
1181        rc->events = event;
1182    } else {
1183        last_event = rc->events;
1184        while (last_event->next != NULL) {
1185            last_event = last_event->next;
1186        }
1187        last_event->next = event;
1188    }
1189
1190    return RTMP_SUCCESS;
1191}
1192
1193
1194rtmp_event_t *rtmp_client_get_event(rtmp_client_t *rc)
1195{
1196    return rc->events;
1197}
1198
1199
1200void rtmp_client_delete_event(rtmp_client_t *rc)
1201{
1202    rtmp_event_t *delete_event;
1203    rtmp_event_t *next_event;
1204
1205    delete_event = rc->events;
1206    free(delete_event->code);
1207    free(delete_event->level);
1208    free(delete_event);
1209
1210    rc->events = next_event;
1211}
1212
1213
1214rtmp_result_t rtmp_client_send_packet(
1215    rtmp_client_t *rc, rtmp_packet_t *packet)
1216{
1217    rtmp_result_t result;
1218    size_t packet_size;
1219
1220    unsigned char fuck[1024];
1221    result = rtmp_packet_serialize(
1222        packet,
1223        fuck,
1224        1024,
1225        rc->amf_chunk_size,
1226        &packet_size);
1227    rtmp_client_set_will_send_buffer(
1228        rc, fuck, packet_size);
1229
1230    return RTMP_SUCCESS;
1231}
1232
1233
1234void rtmp_client_connect(
1235    rtmp_client_t *rc
1236    /* FIXME: take URL */)
1237{
1238    rtmp_packet_t *rtmp_packet;
1239    amf_packet_t *amf_object;
1240
1241    rtmp_packet = (rtmp_packet_t*)rc->data;
1242    rtmp_packet_cleanup(rtmp_packet);
1243    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
1244    rtmp_packet->object_id = 3;
1245
1246    rc->message_number++;
1247    rtmp_packet_add_amf(
1248        rtmp_packet,
1249        amf_packet_create_string("connect"));
1250    rtmp_packet_add_amf(
1251        rtmp_packet,
1252        amf_packet_create_number((double)rc->message_number));
1253
1254    amf_object = amf_packet_create_object();
1255    amf_packet_add_property_to_object(
1256//        amf_object, "app", amf_packet_create_string("live/"));
1257        amf_object, "app", amf_packet_create_string("fastplay/"));
1258    amf_packet_add_property_to_object(
1259        amf_object, "flashVer", amf_packet_create_string("WIN 10,0,12,36"));
1260    amf_packet_add_property_to_object(
1261        amf_object, "swfUrl", amf_packet_create_undefined());
1262    amf_packet_add_property_to_object(
1263        amf_object, "tcUrl",
1264//        amf_packet_create_string("rtmp://127.0.0.1:1935/live/"));
1265        amf_packet_create_string("rtmp://127.0.0.1:2935/fastplay/"));
1266    amf_packet_add_property_to_object(
1267        amf_object, "fpad", amf_packet_create_boolean(0));
1268    amf_packet_add_property_to_object(
1269        amf_object, "capabilities", amf_packet_create_number(15.0));
1270    amf_packet_add_property_to_object(
1271        amf_object, "audioCodecs", amf_packet_create_number(1639.0));
1272    amf_packet_add_property_to_object(
1273        amf_object, "videoCodecs", amf_packet_create_number(252.0));
1274    amf_packet_add_property_to_object(
1275        amf_object, "videoFunction", amf_packet_create_number(1.0));
1276    amf_packet_add_property_to_object(
1277        amf_object, "pageUrl", amf_packet_create_undefined());
1278    amf_packet_add_property_to_object(
1279        amf_object, "objectEncoding", amf_packet_create_number(0.0));
1280    rtmp_packet_add_amf(rtmp_packet, amf_object);
1281
1282    rtmp_client_send_packet(rc, rtmp_packet);
1283}
1284
1285
1286void rtmp_client_create_stream(rtmp_client_t *rc)
1287{
1288    rtmp_packet_t *rtmp_packet;
1289
1290    rtmp_packet = (rtmp_packet_t*)rc->data;
1291    rtmp_packet_cleanup(rtmp_packet);
1292    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
1293    rtmp_packet->object_id = 3;
1294
1295    rc->message_number++;
1296    rtmp_packet_add_amf(
1297        rtmp_packet,
1298        amf_packet_create_string("createStream"));
1299    rtmp_packet_add_amf(
1300        rtmp_packet,
1301        amf_packet_create_number((double)rc->message_number));
1302    rtmp_packet_add_amf(
1303        rtmp_packet,
1304        amf_packet_create_null());
1305
1306    rtmp_client_send_packet(rc, rtmp_packet);
1307}
1308
1309
1310void rtmp_client_play(rtmp_client_t *rc)
1311{
1312    rtmp_packet_t *rtmp_packet;
1313
1314    rtmp_packet = (rtmp_packet_t*)rc->data;
1315    rtmp_packet_cleanup(rtmp_packet);
1316    rtmp_packet->data_type = RTMP_DATATYPE_INVOKE;
1317    rtmp_packet->object_id = 3;
1318
1319    rc->message_number++;
1320    rtmp_packet_add_amf(
1321        rtmp_packet,
1322        amf_packet_create_string("play"));
1323    rtmp_packet_add_amf(
1324        rtmp_packet,
1325        amf_packet_create_number((double)rc->message_number));
1326    rtmp_packet_add_amf(
1327        rtmp_packet,
1328        amf_packet_create_null());
1329    rtmp_packet_add_amf(
1330        rtmp_packet,
1331        amf_packet_create_string("test.mp4"));
1332
1333    rtmp_client_send_packet(rc, rtmp_packet);
1334}
1335
Note: See TracBrowser for help on using the browser.