aboutsummaryrefslogtreecommitdiff
path: root/srtserver.c
blob: 65bc46dd53ae36445bca23e39bb46fd1f1c5d001 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "srtserver.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>

#if defined(_WIN32)
    #include <winsock2.h>
#else
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/poll.h>
    #include <sys/time.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <arpa/inet.h>
#endif

#include <srt/srt.h>

#include "ezlive_config.h"

#define BUFFER_SIZE 1500

int handshake_callback(void* opaq, SRTSOCKET ns, int hs_version, const struct sockaddr* peeraddr, const char* streamid) {
    char addr_str[INET_ADDRSTRLEN];
    struct sockaddr_in* sin = (struct sockaddr_in*)peeraddr;
    inet_ntop(AF_INET, &(sin->sin_addr), addr_str, INET_ADDRSTRLEN);

    printf("[Callback] Incoming connection from: %s:%d\n", addr_str, ntohs(sin->sin_port));
    printf("[Callback] Client Stream ID: %s\n", streamid);
    
    if (streamid == NULL || strlen(streamid) == 0) {
        printf("[Callback] Rejected: No Stream ID provided.\n");
        return -1;
    }

	if (strlen(ezlive_config->key) == 0) {
		printf("[Callback] No key. Skip auth.\n");
		return 0;
	}
    if (strcmp(streamid, ezlive_config->key) != 0) {
        printf("[Callback] Rejected: Invalid Key. Expected '%s', got '%s'\n", ezlive_config->key, streamid);
        return -1;
    }

    printf("[Callback] Key validated. Connection Accepted.\n");
    return 0;
}

void start_srt_server(SrtCallbacks srtcb, void *ctx) {
    if (srt_startup() != 0) {
        fprintf(stderr, "SRT startup failed.\n");
        return;
    }

    SRTSOCKET bind_sock = srt_create_socket();
    if (bind_sock == SRT_INVALID_SOCK) {
        fprintf(stderr, "Error creating socket: %s\n", srt_getlasterror_str());
        return;
    }

    int yes = 1;
    srt_setsockopt(bind_sock, 0, SRTO_RCVSYN, &yes, sizeof(yes));

    struct sockaddr_in sa;
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(ezlive_config->listening_port);
	if (inet_pton(AF_INET, ezlive_config->listening_addr, &sa.sin_addr.s_addr) <= 0) {
		fprintf(stderr, "Invalid IP address\n");
		exit(-1);
	}

    if (srt_bind(bind_sock, (struct sockaddr*)&sa, sizeof(sa)) == SRT_ERROR) {
        fprintf(stderr, "Bind error: %s\n", srt_getlasterror_str());
        srt_close(bind_sock);
        srt_cleanup();
        return;
    }
	srt_listen_callback(bind_sock, handshake_callback, NULL);
    printf("SRT Server listening on port %d...\n", ezlive_config->listening_port);
    if (srt_listen(bind_sock, 5) == SRT_ERROR) {
        fprintf(stderr, "Listen error: %s\n", srt_getlasterror_str());
        return;
    }

    while (1) {
        struct sockaddr_storage client_sa;
        int sa_len = sizeof(client_sa);

        printf("Waiting for client to connect...\n");

        SRTSOCKET client_sock = srt_accept(bind_sock, (struct sockaddr*)&client_sa, &sa_len);
        if (client_sock == SRT_INVALID_SOCK) {
            fprintf(stderr, "Accept error: %s\n", srt_getlasterror_str());
            continue;
        }

        printf("Client connected! Starting to receive data.\n");
		srtcb.on_start(ctx);

        char buffer[BUFFER_SIZE];

        while (1) {
            int n = srt_recvmsg(client_sock, buffer, sizeof(buffer));

            if (n == SRT_ERROR) {
                fprintf(stderr, "Connection lost or error: %s\n", srt_getlasterror_str());
				srtcb.on_stop(ctx);
                break;
            }

            if (n == 0) {
                printf("Client closed connection.\n");
				srtcb.on_stop(ctx);
                break;
            }
			srtcb.on_data(ctx, buffer, n);
        }
        printf("Closing client socket.\n");
        srt_close(client_sock);
    }

    srt_close(bind_sock);
    srt_cleanup();
    return;
}