diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-10-06 13:19:16 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-10-06 13:19:16 +0000 |
commit | 4a5fc4b938bc98a2edc71d4875779619d0cebeec (patch) | |
tree | a816afcf4e6d7c25e0ea8217dc89d810b8fa1eac /src/core/gnunet-service-core_sessions.c | |
parent | 2fb1bb841a5a7ce3783d84cea68938a8202928aa (diff) | |
download | gnunet-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.c | 213 |
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 | */ | ||
1170 | void | ||
1171 | GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client) | ||
1172 | { | ||
1173 | /* notify new client about existing neighbours */ | ||
1174 | GNUNET_CONTAINER_multihashmap_iterate (neighbours, | ||
1175 | ¬ify_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 | */ | ||
1188 | void | ||
1189 | GSC_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 | */ | ||
1228 | void | ||
1229 | GSC_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 | */ | ||
1247 | void | ||
1248 | GSC_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 | |||
1164 | int | 1377 | int |
1165 | GSC_NEIGHBOURS_init () | 1378 | GSC_NEIGHBOURS_init () |
1166 | { | 1379 | { |