aboutsummaryrefslogtreecommitdiff
path: root/src/core/gnunet-service-core_sessions.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-10-06 13:19:16 +0000
committerChristian Grothoff <christian@grothoff.org>2011-10-06 13:19:16 +0000
commit4a5fc4b938bc98a2edc71d4875779619d0cebeec (patch)
treea816afcf4e6d7c25e0ea8217dc89d810b8fa1eac /src/core/gnunet-service-core_sessions.c
parent2fb1bb841a5a7ce3783d84cea68938a8202928aa (diff)
downloadgnunet-4a5fc4b938bc98a2edc71d4875779619d0cebeec.tar.gz
gnunet-4a5fc4b938bc98a2edc71d4875779619d0cebeec.zip
stuff
Diffstat (limited to 'src/core/gnunet-service-core_sessions.c')
-rw-r--r--src/core/gnunet-service-core_sessions.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
index 23d53022e..e388aa9ea 100644
--- a/src/core/gnunet-service-core_sessions.c
+++ b/src/core/gnunet-service-core_sessions.c
@@ -1161,6 +1161,219 @@ create_neighbour (const struct GNUNET_PeerIdentity *pid)
1161} 1161}
1162 1162
1163 1163
1164
1165/**
1166 * We have a new client, notify it about all current sessions.
1167 *
1168 * @param client the new client
1169 */
1170void
1171GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client)
1172{
1173 /* notify new client about existing neighbours */
1174 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
1175 &notify_client_about_neighbour, client);
1176}
1177
1178
1179/**
1180 * Queue a request from a client for transmission to a particular peer.
1181 *
1182 * @param car request to queue; this handle is then shared between
1183 * the caller (CLIENTS subsystem) and SESSIONS and must not
1184 * be released by either until either 'GNUNET_SESSIONS_dequeue',
1185 * 'GNUNET_SESSIONS_transmit' or 'GNUNET_CLIENTS_failed'
1186 * have been invoked on it
1187 */
1188void
1189GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car)
1190{
1191 struct Neighbour *n; // FIXME: session...
1192
1193 n = find_neighbour (&car->peer);
1194 if ((n == NULL) || (GNUNET_YES != n->is_connected) ||
1195 (n->status != PEER_STATE_KEY_CONFIRMED))
1196 {
1197 /* neighbour must have disconnected since request was issued,
1198 * ignore (client will realize it once it processes the
1199 * disconnect notification) */
1200#if DEBUG_CORE_CLIENT
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1202 "Dropped client request for transmission (am disconnected)\n");
1203#endif
1204 GNUNET_STATISTICS_update (stats,
1205 gettext_noop
1206 ("# send requests dropped (disconnected)"), 1,
1207 GNUNET_NO);
1208 GSC_CLIENTS_reject_requests (car);
1209 return;
1210 }
1211#if DEBUG_CORE_CLIENT
1212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213 "Received client transmission request. queueing\n");
1214#endif
1215 GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
1216 n->active_client_request_tail, car);
1217
1218 // schedule_peer_messages (n);
1219}
1220
1221
1222/**
1223 * Dequeue a request from a client from transmission to a particular peer.
1224 *
1225 * @param car request to dequeue; this handle will then be 'owned' by
1226 * the caller (CLIENTS sysbsystem)
1227 */
1228void
1229GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car)
1230{
1231 struct Session *s;
1232
1233 s = find_session (&car->peer);
1234 GNUNET_CONTAINER_DLL_remove (s->active_client_request_head,
1235 s->active_client_request_tail, car);
1236}
1237
1238
1239
1240/**
1241 * Transmit a message to a particular peer.
1242 *
1243 * @param car original request that was queued and then solicited;
1244 * this handle will now be 'owned' by the SESSIONS subsystem
1245 * @param msg message to transmit
1246 */
1247void
1248GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
1249 const struct GNUNET_MessageHeader *msg)
1250{
1251 struct MessageEntry *prev;
1252 struct MessageEntry *pos;
1253 struct MessageEntry *e;
1254 struct MessageEntry *min_prio_entry;
1255 struct MessageEntry *min_prio_prev;
1256 unsigned int min_prio;
1257 unsigned int queue_size;
1258
1259 n = find_neighbour (&sm->peer);
1260 if ((n == NULL) || (GNUNET_YES != n->is_connected) ||
1261 (n->status != PEER_STATE_KEY_CONFIRMED))
1262 {
1263 /* attempt to send message to peer that is not connected anymore
1264 * (can happen due to asynchrony) */
1265 GNUNET_STATISTICS_update (stats,
1266 gettext_noop
1267 ("# messages discarded (disconnected)"), 1,
1268 GNUNET_NO);
1269 if (client != NULL)
1270 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1271 return;
1272 }
1273#if DEBUG_CORE
1274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1275 "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
1276 "SEND", (unsigned int) msize, GNUNET_i2s (&sm->peer));
1277#endif
1278 discard_expired_messages (n);
1279 /* bound queue size */
1280 /* NOTE: this entire block to bound the queue size should be
1281 * obsolete with the new client-request code and the
1282 * 'schedule_peer_messages' mechanism; we still have this code in
1283 * here for now as a sanity check for the new mechanmism;
1284 * ultimately, we should probably simply reject SEND messages that
1285 * are not 'approved' (or provide a new core API for very unreliable
1286 * delivery that always sends with priority 0). Food for thought. */
1287 min_prio = UINT32_MAX;
1288 min_prio_entry = NULL;
1289 min_prio_prev = NULL;
1290 queue_size = 0;
1291 prev = NULL;
1292 pos = n->messages;
1293 while (pos != NULL)
1294 {
1295 if (pos->priority <= min_prio)
1296 {
1297 min_prio_entry = pos;
1298 min_prio_prev = prev;
1299 min_prio = pos->priority;
1300 }
1301 queue_size++;
1302 prev = pos;
1303 pos = pos->next;
1304 }
1305 if (queue_size >= MAX_PEER_QUEUE_SIZE)
1306 {
1307 /* queue full */
1308 if (ntohl (sm->priority) <= min_prio)
1309 {
1310 /* discard new entry; this should no longer happen! */
1311 GNUNET_break (0);
1312#if DEBUG_CORE
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1314 "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
1315 queue_size, (unsigned int) MAX_PEER_QUEUE_SIZE,
1316 (unsigned int) msize, (unsigned int) ntohs (message->type));
1317#endif
1318 GNUNET_STATISTICS_update (stats,
1319 gettext_noop ("# discarded CORE_SEND requests"),
1320 1, GNUNET_NO);
1321
1322 if (client != NULL)
1323 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1324 return;
1325 }
1326 GNUNET_assert (min_prio_entry != NULL);
1327 /* discard "min_prio_entry" */
1328#if DEBUG_CORE
1329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1330 "Queue full, discarding existing older request\n");
1331#endif
1332 GNUNET_STATISTICS_update (stats,
1333 gettext_noop
1334 ("# discarded lower priority CORE_SEND requests"),
1335 1, GNUNET_NO);
1336 if (min_prio_prev == NULL)
1337 n->messages = min_prio_entry->next;
1338 else
1339 min_prio_prev->next = min_prio_entry->next;
1340 GNUNET_free (min_prio_entry);
1341 }
1342
1343#if DEBUG_CORE
1344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1345 "Adding transmission request for `%4s' of size %u to queue\n",
1346 GNUNET_i2s (&sm->peer), (unsigned int) msize);
1347#endif
1348 e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
1349 e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
1350 e->priority = ntohl (sm->priority);
1351 e->size = msize;
1352 if (GNUNET_YES != (int) ntohl (sm->cork))
1353 e->got_slack = GNUNET_YES;
1354 memcpy (&e[1], &sm[1], msize);
1355
1356 /* insert, keep list sorted by deadline */
1357 prev = NULL;
1358 pos = n->messages;
1359 while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
1360 {
1361 prev = pos;
1362 pos = pos->next;
1363 }
1364 if (prev == NULL)
1365 n->messages = e;
1366 else
1367 prev->next = e;
1368 e->next = pos;
1369
1370 /* consider scheduling now */
1371 process_plaintext_neighbour_queue (n);
1372
1373}
1374
1375
1376
1164int 1377int
1165GSC_NEIGHBOURS_init () 1378GSC_NEIGHBOURS_init ()
1166{ 1379{