source: mainline/uspace/srv/udp/assoc.c@ ee603c4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ee603c4 was ee603c4, checked in by Jiri Svoboda <jiri@…>, 14 years ago

UDP associations, sending datagrams.

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup udp
30 * @{
31 */
32
33/**
34 * @file UDP associations
35 */
36
37#include <adt/list.h>
38#include <bool.h>
39#include <fibril_synch.h>
40#include <io/log.h>
41#include <stdlib.h>
42
43#include "assoc.h"
44#include "msg.h"
45#include "pdu.h"
46#include "ucall.h"
47#include "udp_inet.h"
48#include "udp_type.h"
49
50LIST_INITIALIZE(assoc_list);
51FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
52
53/** Create new association structure.
54 *
55 * @param lsock Local socket (will be deeply copied)
56 * @param fsock Foreign socket (will be deeply copied)
57 * @return New association or NULL
58 */
59udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock)
60{
61 udp_assoc_t *assoc = NULL;
62
63 /* Allocate connection structure */
64 assoc = calloc(1, sizeof(udp_assoc_t));
65 if (assoc == NULL)
66 goto error;
67
68 fibril_mutex_initialize(&assoc->lock);
69
70 /* One for the user */
71 atomic_set(&assoc->refcnt, 1);
72
73 /* Initialize receive queue */
74 list_initialize(&assoc->rcv_queue);
75 fibril_condvar_initialize(&assoc->rcv_queue_cv);
76
77 if (lsock != NULL)
78 assoc->ident.local = *lsock;
79 if (fsock != NULL)
80 assoc->ident.foreign = *fsock;
81
82 return assoc;
83error:
84 return NULL;
85}
86
87/** Destroy association structure.
88 *
89 * Association structure should be destroyed when the folowing conditions
90 * are met:
91 * (1) user has deleted the association
92 * (2) nobody is holding references to the association
93 *
94 * This happens when @a assoc->refcnt is zero as we count (1)
95 * as an extra reference.
96 *
97 * @param conn Connection
98 */
99static void udp_assoc_free(udp_assoc_t *assoc)
100{
101 log_msg(LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
102
103 while (!list_empty(&assoc->rcv_queue)) {
104 link_t *link = list_first(&assoc->rcv_queue);
105// ....;
106 list_remove(link);
107 }
108
109 free(assoc);
110}
111
112/** Add reference to association.
113 *
114 * Increase association reference count by one.
115 *
116 * @param assoc Association
117 */
118void udp_assoc_addref(udp_assoc_t *assoc)
119{
120 log_msg(LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
121 atomic_inc(&assoc->refcnt);
122}
123
124/** Remove reference from association.
125 *
126 * Decrease association reference count by one.
127 *
128 * @param assoc Association
129 */
130void udp_assoc_delref(udp_assoc_t *assoc)
131{
132 log_msg(LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
133
134 if (atomic_predec(&assoc->refcnt) == 0)
135 udp_assoc_free(assoc);
136}
137
138/** Delete association.
139 *
140 * The caller promises not make no further references to @a assoc.
141 * UDP will free @a assoc eventually.
142 *
143 * @param assoc Association
144 */
145void udp_assoc_delete(udp_assoc_t *assoc)
146{
147 log_msg(LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
148
149 assert(assoc->deleted == false);
150 udp_assoc_delref(assoc);
151 assoc->deleted = true;
152}
153
154/** Enlist association.
155 *
156 * Add association to the association map.
157 */
158void udp_assoc_add(udp_assoc_t *assoc)
159{
160 udp_assoc_addref(assoc);
161 fibril_mutex_lock(&assoc_list_lock);
162 list_append(&assoc->link, &assoc_list);
163 fibril_mutex_unlock(&assoc_list_lock);
164}
165
166/** Delist association.
167 *
168 * Remove association from the association map.
169 */
170void udp_assoc_remove(udp_assoc_t *assoc)
171{
172 fibril_mutex_lock(&assoc_list_lock);
173 list_remove(&assoc->link);
174 fibril_mutex_unlock(&assoc_list_lock);
175 udp_assoc_delref(assoc);
176}
177
178/** Set foreign socket in association.
179 *
180 * @param assoc Association
181 * @param fsock Foreign socket (deeply copied)
182 */
183void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
184{
185 log_msg(LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
186 fibril_mutex_lock(&assoc->lock);
187 assoc->ident.foreign = *fsock;
188 fibril_mutex_unlock(&assoc->lock);
189}
190
191/** Set local socket in association.
192 *
193 * @param assoc Association
194 * @param fsock Foreign socket (deeply copied)
195 */
196void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
197{
198 log_msg(LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
199 fibril_mutex_lock(&assoc->lock);
200 assoc->ident.local = *lsock;
201 fibril_mutex_unlock(&assoc->lock);
202}
203
204/** Send message to association.
205 *
206 * @param assoc Association
207 * @param fsock Foreign socket or NULL not to override @a assoc
208 * @param msg Message
209 *
210 * @return EOK on success
211 * EINVAL if foreign socket is not set
212 * ENOMEM if out of resources
213 * EIO if no route to destination exists
214 */
215int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg)
216{
217 udp_pdu_t *pdu;
218 udp_sockpair_t sp;
219 int rc;
220
221 /* @a fsock can be used to override the foreign socket */
222 sp = assoc->ident;
223 if (fsock != NULL)
224 sp.foreign = *fsock;
225
226 if (sp.foreign.addr.ipv4 == 0 || sp.foreign.port == 0)
227 return EINVAL;
228
229 rc = udp_pdu_encode(&sp, msg, &pdu);
230 if (rc != EOK)
231 return ENOMEM;
232
233 rc = udp_transmit_pdu(pdu);
234 if (rc != EOK)
235 return EIO;
236
237 udp_pdu_delete(pdu);
238
239 return EOK;
240}
241
242/**
243 * @}
244 */
Note: See TracBrowser for help on using the repository browser.