1 /**
2 * Copyright (c) 2020 Paul-Louis Ageneau
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "juice.h"
20 #include "addr.h"
21 #include "agent.h"
22 #include "ice.h"
23
24 #ifndef NO_SERVER
25 #include "server.h"
26 #endif
27
28 #include <stdio.h>
29
juice_create(const juice_config_t * config)30 JUICE_EXPORT juice_agent_t *juice_create(const juice_config_t *config) {
31 if (!config)
32 return NULL;
33
34 return agent_create(config);
35 }
36
juice_destroy(juice_agent_t * agent)37 JUICE_EXPORT void juice_destroy(juice_agent_t *agent) {
38 if (agent)
39 agent_destroy(agent);
40 }
41
juice_gather_candidates(juice_agent_t * agent)42 JUICE_EXPORT int juice_gather_candidates(juice_agent_t *agent) {
43 if (!agent)
44 return JUICE_ERR_INVALID;
45
46 if (agent_gather_candidates(agent) < 0)
47 return JUICE_ERR_FAILED;
48
49 return JUICE_ERR_SUCCESS;
50 }
51
juice_get_local_description(juice_agent_t * agent,char * buffer,size_t size)52 JUICE_EXPORT int juice_get_local_description(juice_agent_t *agent, char *buffer, size_t size) {
53 if (!agent || (!buffer && size))
54 return JUICE_ERR_INVALID;
55
56 if (agent_get_local_description(agent, buffer, size) < 0)
57 return JUICE_ERR_FAILED;
58
59 return JUICE_ERR_SUCCESS;
60 }
61
juice_set_remote_description(juice_agent_t * agent,const char * sdp)62 JUICE_EXPORT int juice_set_remote_description(juice_agent_t *agent, const char *sdp) {
63 if (!agent || !sdp)
64 return JUICE_ERR_INVALID;
65
66 if (agent_set_remote_description(agent, sdp) < 0)
67 return JUICE_ERR_FAILED;
68
69 return JUICE_ERR_SUCCESS;
70 }
71
juice_add_remote_candidate(juice_agent_t * agent,const char * sdp)72 JUICE_EXPORT int juice_add_remote_candidate(juice_agent_t *agent, const char *sdp) {
73 if (!agent || !sdp)
74 return JUICE_ERR_INVALID;
75
76 if (agent_add_remote_candidate(agent, sdp) < 0)
77 return JUICE_ERR_FAILED;
78
79 return JUICE_ERR_SUCCESS;
80 }
81
juice_set_remote_gathering_done(juice_agent_t * agent)82 JUICE_EXPORT int juice_set_remote_gathering_done(juice_agent_t *agent) {
83 if (!agent)
84 return JUICE_ERR_INVALID;
85
86 if (agent_set_remote_gathering_done(agent) < 0)
87 return JUICE_ERR_FAILED;
88
89 return JUICE_ERR_SUCCESS;
90 }
91
juice_send(juice_agent_t * agent,const char * data,size_t size)92 JUICE_EXPORT int juice_send(juice_agent_t *agent, const char *data, size_t size) {
93 if (!agent || (!data && size))
94 return JUICE_ERR_INVALID;
95
96 if (agent_send(agent, data, size, 0) < 0)
97 return JUICE_ERR_FAILED;
98
99 return JUICE_ERR_SUCCESS;
100 }
101
juice_send_diffserv(juice_agent_t * agent,const char * data,size_t size,int ds)102 JUICE_EXPORT int juice_send_diffserv(juice_agent_t *agent, const char *data, size_t size, int ds) {
103 if (!agent || (!data && size))
104 return JUICE_ERR_INVALID;
105
106 if (agent_send(agent, data, size, ds) < 0)
107 return JUICE_ERR_FAILED;
108
109 return JUICE_ERR_SUCCESS;
110 }
111
juice_get_state(juice_agent_t * agent)112 JUICE_EXPORT juice_state_t juice_get_state(juice_agent_t *agent) { return agent_get_state(agent); }
113
juice_get_selected_candidates(juice_agent_t * agent,char * local,size_t local_size,char * remote,size_t remote_size)114 JUICE_EXPORT int juice_get_selected_candidates(juice_agent_t *agent, char *local, size_t local_size,
115 char *remote, size_t remote_size) {
116 if (!agent || (!local && local_size) || (!remote && remote_size))
117 return JUICE_ERR_INVALID;
118
119 ice_candidate_t local_cand, remote_cand;
120 if (agent_get_selected_candidate_pair(agent, &local_cand, &remote_cand))
121 return JUICE_ERR_NOT_AVAIL;
122
123 if (local_size && ice_generate_candidate_sdp(&local_cand, local, local_size) < 0)
124 return JUICE_ERR_FAILED;
125
126 if (remote_size && ice_generate_candidate_sdp(&remote_cand, remote, remote_size) < 0)
127 return JUICE_ERR_FAILED;
128
129 return JUICE_ERR_SUCCESS;
130 }
131
juice_get_selected_addresses(juice_agent_t * agent,char * local,size_t local_size,char * remote,size_t remote_size)132 JUICE_EXPORT int juice_get_selected_addresses(juice_agent_t *agent, char *local, size_t local_size,
133 char *remote, size_t remote_size) {
134 if (!agent || (!local && local_size) || (!remote && remote_size))
135 return JUICE_ERR_INVALID;
136
137 ice_candidate_t local_cand, remote_cand;
138 if (agent_get_selected_candidate_pair(agent, &local_cand, &remote_cand))
139 return JUICE_ERR_NOT_AVAIL;
140
141 if (local_size && addr_record_to_string(&local_cand.resolved, local, local_size) < 0)
142 return JUICE_ERR_FAILED;
143
144 if (remote_size && addr_record_to_string(&remote_cand.resolved, remote, remote_size) < 0)
145 return JUICE_ERR_FAILED;
146
147 return JUICE_ERR_SUCCESS;
148 }
149
juice_state_to_string(juice_state_t state)150 JUICE_EXPORT const char *juice_state_to_string(juice_state_t state) {
151 switch (state) {
152 case JUICE_STATE_DISCONNECTED:
153 return "disconnected";
154 case JUICE_STATE_GATHERING:
155 return "gathering";
156 case JUICE_STATE_CONNECTING:
157 return "connecting";
158 case JUICE_STATE_CONNECTED:
159 return "connected";
160 case JUICE_STATE_COMPLETED:
161 return "completed";
162 case JUICE_STATE_FAILED:
163 return "failed";
164 default:
165 return "unknown";
166 }
167 }
168
juice_server_create(const juice_server_config_t * config)169 JUICE_EXPORT juice_server_t *juice_server_create(const juice_server_config_t *config) {
170 #ifndef NO_SERVER
171 if (!config)
172 return NULL;
173
174 return server_create(config);
175 #else
176 (void)config;
177 JLOG_FATAL("The library was compiled without server support");
178 return NULL;
179 #endif
180 }
181
juice_server_destroy(juice_server_t * server)182 JUICE_EXPORT void juice_server_destroy(juice_server_t *server) {
183 #ifndef NO_SERVER
184 if (server)
185 server_destroy(server);
186 #else
187 (void)server;
188 #endif
189 }
190
juice_server_get_port(juice_server_t * server)191 JUICE_EXPORT uint16_t juice_server_get_port(juice_server_t *server) {
192 #ifndef NO_SERVER
193 return server ? server_get_port(server) : 0;
194 #else
195 (void)server;
196 return 0;
197 #endif
198 }
199
juice_server_add_credentials(juice_server_t * server,const juice_server_credentials_t * credentials,unsigned long lifetime_ms)200 JUICE_EXPORT int juice_server_add_credentials(juice_server_t *server,
201 const juice_server_credentials_t *credentials,
202 unsigned long lifetime_ms) {
203 #ifndef NO_SERVER
204 if (!server || !credentials)
205 return JUICE_ERR_INVALID;
206
207 if (server_add_credentials(server, credentials, (timediff_t)lifetime_ms) < 0)
208 return JUICE_ERR_FAILED;
209
210 return JUICE_ERR_SUCCESS;
211 #else
212 (void)server;
213 (void)credentials;
214 (void)lifetime_ms;
215 return JUICE_ERR_INVALID;
216 #endif
217 }
218