~ubuntu-branches/debian/experimental/libnice/experimental

« back to all changes in this revision

Viewing changes to socket/udp-bsd.c

  • Committer: Package Import Robot
  • Author(s): Simon McVittie
  • Date: 2014-03-31 18:09:02 UTC
  • mfrom: (1.4.2) (10.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140331180902-cteej34g3614ixtq
Tags: 0.1.5+rc20140331-0exp1
* Upstream release candidate for build-testing on miscellaneous
  architectures' buildds
* Build with `make -k` to get better logs if it fails

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
 
58
58
 
59
59
static void socket_close (NiceSocket *sock);
60
 
static gint socket_recv (NiceSocket *sock, NiceAddress *from,
61
 
    guint len, gchar *buf);
62
 
static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
63
 
    guint len, const gchar *buf);
 
60
static gint socket_recv_messages (NiceSocket *sock,
 
61
    NiceInputMessage *recv_messages, guint n_recv_messages);
 
62
static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
 
63
    const NiceOutputMessage *messages, guint n_messages);
64
64
static gboolean socket_is_reliable (NiceSocket *sock);
65
65
 
66
66
struct UdpBsdSocketPrivate
72
72
NiceSocket *
73
73
nice_udp_bsd_socket_new (NiceAddress *addr)
74
74
{
75
 
  struct sockaddr_storage name;
 
75
  union {
 
76
    struct sockaddr_storage storage;
 
77
    struct sockaddr addr;
 
78
  } name;
76
79
  NiceSocket *sock = g_slice_new0 (NiceSocket);
77
80
  GSocket *gsock = NULL;
78
81
  gboolean gret = FALSE;
80
83
  struct UdpBsdSocketPrivate *priv;
81
84
 
82
85
  if (addr != NULL) {
83
 
    nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
 
86
    nice_address_copy_to_sockaddr(addr, &name.addr);
84
87
  } else {
85
88
    memset (&name, 0, sizeof (name));
86
 
    name.ss_family = AF_UNSPEC;
 
89
    name.storage.ss_family = AF_UNSPEC;
87
90
  }
88
91
 
89
 
  if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
 
92
  if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
90
93
    gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
91
94
        G_SOCKET_PROTOCOL_UDP, NULL);
92
 
    name.ss_family = AF_INET;
 
95
    name.storage.ss_family = AF_INET;
93
96
#ifdef HAVE_SA_LEN
94
 
    name.ss_len = sizeof (struct sockaddr_in);
 
97
    name.storage.ss_len = sizeof (struct sockaddr_in);
95
98
#endif
96
 
  } else if (name.ss_family == AF_INET6) {
 
99
  } else if (name.storage.ss_family == AF_INET6) {
97
100
    gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
98
101
        G_SOCKET_PROTOCOL_UDP, NULL);
99
 
    name.ss_family = AF_INET6;
 
102
    name.storage.ss_family = AF_INET6;
100
103
#ifdef HAVE_SA_LEN
101
 
    name.ss_len = sizeof (struct sockaddr_in6);
 
104
    name.storage.ss_len = sizeof (struct sockaddr_in6);
102
105
#endif
103
106
  }
104
107
 
109
112
 
110
113
  /* GSocket: All socket file descriptors are set to be close-on-exec. */
111
114
  g_socket_set_blocking (gsock, false);
112
 
  gaddr = g_socket_address_new_from_native (&name, sizeof (name));
 
115
  gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
113
116
  if (gaddr != NULL) {
114
117
    gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
115
118
    g_object_unref (gaddr);
124
127
 
125
128
  gaddr = g_socket_get_local_address (gsock, NULL);
126
129
  if (gaddr == NULL ||
127
 
      !g_socket_address_to_native (gaddr, &name, sizeof(name), NULL)) {
 
130
      !g_socket_address_to_native (gaddr, &name.addr, sizeof(name), NULL)) {
128
131
    g_slice_free (NiceSocket, sock);
129
132
    g_socket_close (gsock, NULL);
130
133
    g_object_unref (gsock);
133
136
 
134
137
  g_object_unref (gaddr);
135
138
 
136
 
  nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
 
139
  nice_address_set_from_sockaddr (&sock->addr, &name.addr);
137
140
 
138
141
  priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
139
142
  nice_address_init (&priv->niceaddr);
140
143
 
141
144
  sock->fileno = gsock;
142
 
  sock->send = socket_send;
143
 
  sock->recv = socket_recv;
 
145
  sock->send_messages = socket_send_messages;
 
146
  sock->recv_messages = socket_recv_messages;
144
147
  sock->is_reliable = socket_is_reliable;
145
148
  sock->close = socket_close;
146
149
 
155
158
  if (priv->gaddr)
156
159
    g_object_unref (priv->gaddr);
157
160
  g_slice_free (struct UdpBsdSocketPrivate, sock->priv);
 
161
  sock->priv = NULL;
158
162
 
159
163
  if (sock->fileno) {
160
164
    g_socket_close (sock->fileno, NULL);
164
168
}
165
169
 
166
170
static gint
167
 
socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
 
171
socket_recv_messages (NiceSocket *sock,
 
172
    NiceInputMessage *recv_messages, guint n_recv_messages)
168
173
{
169
 
  GSocketAddress *gaddr = NULL;
170
 
  GError *gerr = NULL;
171
 
  gint recvd;
172
 
 
173
 
  recvd = g_socket_receive_from (sock->fileno, &gaddr, buf, len, NULL, &gerr);
174
 
 
175
 
  if (recvd < 0) {
176
 
    if (g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)
177
 
        || g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_FAILED))
178
 
      recvd = 0;
179
 
 
180
 
    g_error_free (gerr);
181
 
  }
182
 
 
183
 
  if (recvd > 0 && from != NULL && gaddr != NULL) {
184
 
    struct sockaddr_storage sa;
185
 
 
186
 
    g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
187
 
    nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
188
 
  }
189
 
 
190
 
  if (gaddr != NULL)
191
 
    g_object_unref (gaddr);
192
 
 
193
 
  return recvd;
 
174
  guint i;
 
175
  gboolean error = FALSE;
 
176
 
 
177
  /* Read messages into recv_messages until one fails or would block, or we
 
178
   * reach the end. */
 
179
  for (i = 0; i < n_recv_messages; i++) {
 
180
    NiceInputMessage *recv_message = &recv_messages[i];
 
181
    GSocketAddress *gaddr = NULL;
 
182
    GError *gerr = NULL;
 
183
    gssize recvd;
 
184
    gint flags = G_SOCKET_MSG_NONE;
 
185
 
 
186
    recvd = g_socket_receive_message (sock->fileno,
 
187
        (recv_message->from != NULL) ? &gaddr : NULL,
 
188
        recv_message->buffers, recv_message->n_buffers, NULL, NULL,
 
189
        &flags, NULL, &gerr);
 
190
 
 
191
    recv_message->length = MAX (recvd, 0);
 
192
 
 
193
    if (recvd < 0) {
 
194
      if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
 
195
        recvd = 0;
 
196
      else
 
197
        error = TRUE;
 
198
 
 
199
      g_error_free (gerr);
 
200
    }
 
201
 
 
202
    if (recvd > 0 && recv_message->from != NULL && gaddr != NULL) {
 
203
      union {
 
204
        struct sockaddr_storage storage;
 
205
        struct sockaddr addr;
 
206
      } sa;
 
207
 
 
208
      g_socket_address_to_native (gaddr, &sa.addr, sizeof (sa), NULL);
 
209
      nice_address_set_from_sockaddr (recv_message->from, &sa.addr);
 
210
    }
 
211
 
 
212
    if (gaddr != NULL)
 
213
      g_object_unref (gaddr);
 
214
 
 
215
    /* Return early on error or EWOULDBLOCK. */
 
216
    if (recvd <= 0)
 
217
      break;
 
218
  }
 
219
 
 
220
  /* Was there an error processing the first message? */
 
221
  if (error && i == 0)
 
222
    return -1;
 
223
 
 
224
  return i;
194
225
}
195
226
 
196
 
static gboolean
197
 
socket_send (NiceSocket *sock, const NiceAddress *to,
198
 
    guint len, const gchar *buf)
 
227
static gssize
 
228
socket_send_message (NiceSocket *sock, const NiceAddress *to,
 
229
    const NiceOutputMessage *message)
199
230
{
200
231
  struct UdpBsdSocketPrivate *priv = sock->priv;
201
 
  ssize_t sent;
 
232
  GError *child_error = NULL;
 
233
  gssize len;
202
234
 
203
235
  if (!nice_address_is_valid (&priv->niceaddr) ||
204
236
      !nice_address_equal (&priv->niceaddr, to)) {
205
 
    struct sockaddr_storage sa;
 
237
    union {
 
238
      struct sockaddr_storage storage;
 
239
      struct sockaddr addr;
 
240
    } sa;
206
241
    GSocketAddress *gaddr;
207
242
 
208
243
    if (priv->gaddr)
209
244
      g_object_unref (priv->gaddr);
210
 
    nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
211
 
    gaddr = g_socket_address_new_from_native (&sa, sizeof(sa));
 
245
 
 
246
    nice_address_copy_to_sockaddr (to, &sa.addr);
 
247
    gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
 
248
    priv->gaddr = gaddr;
 
249
 
212
250
    if (gaddr == NULL)
213
251
      return -1;
214
 
    priv->gaddr = gaddr;
 
252
 
215
253
    priv->niceaddr = *to;
216
254
  }
217
255
 
218
 
  sent = g_socket_send_to (sock->fileno, priv->gaddr, buf, len, NULL, NULL);
219
 
 
220
 
  return sent == (ssize_t)len;
 
256
  len = g_socket_send_message (sock->fileno, priv->gaddr, message->buffers,
 
257
      message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &child_error);
 
258
 
 
259
  if (len < 0) {
 
260
    if (g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
 
261
      len = 0;
 
262
 
 
263
    g_error_free (child_error);
 
264
  }
 
265
 
 
266
  return len;
 
267
}
 
268
 
 
269
static gint
 
270
socket_send_messages (NiceSocket *sock, const NiceAddress *to,
 
271
    const NiceOutputMessage *messages, guint n_messages)
 
272
{
 
273
  guint i;
 
274
 
 
275
  for (i = 0; i < n_messages; i++) {
 
276
    const NiceOutputMessage *message = &messages[i];
 
277
    gssize len;
 
278
 
 
279
    len = socket_send_message (sock, to, message);
 
280
 
 
281
    if (len < 0) {
 
282
      /* Error. */
 
283
      return len;
 
284
    } else if (len == 0) {
 
285
      /* EWOULDBLOCK. */
 
286
      break;
 
287
    }
 
288
  }
 
289
 
 
290
  return i;
221
291
}
222
292
 
223
293
static gboolean