1342
static inline void __tunnel_socket_add_fin_to_pipe(TunnelChannel *channel, RedSocket *sckt)
1342
static inline void __tunnel_socket_add_fin_to_pipe(TunnelChannelClient *channel, RedSocket *sckt)
1344
ASSERT(!red_channel_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item));
1344
ASSERT(!red_channel_client_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item));
1345
1345
sckt->out_data.status_pipe_item.type = PIPE_ITEM_TYPE_SOCKET_FIN;
1346
red_channel_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
1346
red_channel_client_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
1349
static inline void __tunnel_socket_add_close_to_pipe(TunnelChannel *channel, RedSocket *sckt)
1349
static inline void __tunnel_socket_add_close_to_pipe(TunnelChannelClient *channel, RedSocket *sckt)
1351
1351
ASSERT(!channel->mig_inprogress);
1353
if (red_channel_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item)) {
1353
if (red_channel_client_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item)) {
1354
1354
ASSERT(sckt->out_data.status_pipe_item.type == PIPE_ITEM_TYPE_SOCKET_FIN);
1355
1355
// close is stronger than FIN
1356
red_channel_pipe_item_remove(&channel->base, &sckt->out_data.status_pipe_item);
1356
red_channel_client_pipe_remove_and_release(&channel->base,
1357
&sckt->out_data.status_pipe_item);
1358
1359
sckt->pushed_close = TRUE;
1359
1360
sckt->out_data.status_pipe_item.type = PIPE_ITEM_TYPE_SOCKET_CLOSE;
1360
red_channel_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
1361
red_channel_client_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
1363
static inline void __tunnel_socket_add_close_ack_to_pipe(TunnelChannel *channel, RedSocket *sckt)
1364
static inline void __tunnel_socket_add_close_ack_to_pipe(TunnelChannelClient *channel, RedSocket *sckt)
1365
1366
ASSERT(!channel->mig_inprogress);
1367
if (red_channel_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item)) {
1368
if (red_channel_client_pipe_item_is_linked(&channel->base, &sckt->out_data.status_pipe_item)) {
1368
1369
ASSERT(sckt->out_data.status_pipe_item.type == PIPE_ITEM_TYPE_SOCKET_FIN);
1369
1370
// close is stronger than FIN
1370
red_channel_pipe_item_remove(&channel->base, &sckt->out_data.status_pipe_item);
1371
red_channel_client_pipe_remove_and_release(&channel->base,
1372
&sckt->out_data.status_pipe_item);
1373
1375
sckt->out_data.status_pipe_item.type = PIPE_ITEM_TYPE_SOCKET_CLOSED_ACK;
1374
red_channel_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
1376
red_channel_client_pipe_add(&channel->base, &sckt->out_data.status_pipe_item);
2334
2347
/* outgoing msgs
2335
2348
********************************/
2337
static void tunnel_channel_send_set_ack(TunnelChannel *channel, PipeItem *item)
2341
channel->base.send_data.u.ack.generation = ++channel->base.ack_data.generation;
2342
channel->base.send_data.u.ack.window = CLIENT_ACK_WINDOW;
2344
red_channel_init_send_data(&channel->base, SPICE_MSG_SET_ACK, item);
2345
red_channel_add_buf(&channel->base, &channel->base.send_data.u.ack, sizeof(SpiceMsgSetAck));
2347
red_channel_begin_send_message(&channel->base);
2350
static void tunnel_channel_send_migrate(TunnelChannel *channel, PipeItem *item)
2353
channel->base.send_data.u.migrate.flags = SPICE_MIGRATE_NEED_FLUSH |
2354
SPICE_MIGRATE_NEED_DATA_TRANSFER;
2355
channel->expect_migrate_mark = TRUE;
2356
red_channel_init_send_data(&channel->base, SPICE_MSG_MIGRATE, item);
2357
red_channel_add_buf(&channel->base, &channel->base.send_data.u.migrate, sizeof(SpiceMsgMigrate));
2358
red_channel_begin_send_message(&channel->base);
2361
static int __tunnel_channel_send_process_bufs_migrate_data(TunnelChannel *channel,
2362
TunneledBufferProcessQueue *queue)
2350
static void tunnel_channel_marshall_migrate(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2352
TunnelChannelClient *tunnel_channel;
2355
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2356
tunnel_channel->send_data.u.migrate.flags =
2357
SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
2358
tunnel_channel->expect_migrate_mark = TRUE;
2359
red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, item);
2360
spice_marshaller_add_ref(m,
2361
(uint8_t*)&tunnel_channel->send_data.u.migrate,
2362
sizeof(SpiceMsgMigrate));
2365
static int __tunnel_channel_marshall_process_bufs_migrate_data(TunnelChannelClient *channel,
2366
SpiceMarshaller *m, TunneledBufferProcessQueue *queue)
2364
2368
int buf_offset = queue->head_offset;
2365
2369
RawTunneledBuffer *buf = queue->head;
2369
red_channel_add_buf(&channel->base, buf->data + buf_offset, buf->size - buf_offset);
2373
spice_marshaller_add_ref(m, (uint8_t*)buf->data + buf_offset, buf->size - buf_offset);
2370
2374
size += buf->size - buf_offset;
2371
2375
buf_offset = 0;
2372
2376
buf = buf->next;
2486
2491
if (item->slirp_socket_size) { // zero if socket is closed
2487
red_channel_add_buf(&channel->base, item->slirp_socket, item->slirp_socket_size);
2492
spice_marshaller_add_ref(m, (uint8_t*)item->slirp_socket, item->slirp_socket_size);
2488
2493
mig_sckt->slirp_sckt = cur_offset;
2489
2494
cur_offset += item->slirp_socket_size;
2491
2496
return (cur_offset - offset);
2494
static void tunnel_channel_send_migrate_data(TunnelChannel *channel, PipeItem *item)
2499
static void tunnel_channel_marshall_migrate_data(RedChannelClient *rcc,
2500
SpiceMarshaller *m, PipeItem *item)
2496
TunnelMigrateData *migrate_data = &channel->send_data.u.migrate_data;
2502
TunnelChannelClient *tunnel_channel;
2503
TunnelMigrateData *migrate_data;
2497
2504
TunnelMigrateItem *migrate_item = (TunnelMigrateItem *)item;
2500
2507
uint32_t data_buf_offset = 0; // current location in data[0] field
2509
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2510
migrate_data = &tunnel_channel->send_data.u.migrate_data;
2503
2512
migrate_data->magic = TUNNEL_MIGRATE_DATA_MAGIC;
2504
2513
migrate_data->version = TUNNEL_MIGRATE_DATA_VERSION;
2505
migrate_data->message_serial = red_channel_get_message_serial(&channel->base);
2506
red_channel_init_send_data(&channel->base, SPICE_MSG_MIGRATE_DATA, item);
2507
red_channel_add_buf(&channel->base, migrate_data, sizeof(*migrate_data));
2514
migrate_data->message_serial = red_channel_client_get_message_serial(rcc);
2515
red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
2516
spice_marshaller_add_ref(m, (uint8_t*)migrate_data, sizeof(*migrate_data));
2509
2518
migrate_data->slirp_state = data_buf_offset;
2510
red_channel_add_buf(&channel->base, migrate_item->slirp_state, migrate_item->slirp_state_size);
2519
spice_marshaller_add_ref(m, (uint8_t*)migrate_item->slirp_state, migrate_item->slirp_state_size);
2511
2520
data_buf_offset += migrate_item->slirp_state_size;
2513
2522
migrate_data->services_list = data_buf_offset;
2514
red_channel_add_buf(&channel->base, migrate_item->services_list,
2523
spice_marshaller_add_ref(m, (uint8_t*)migrate_item->services_list,
2515
2524
migrate_item->services_list_size);
2516
2525
data_buf_offset += migrate_item->services_list_size;
2518
2527
for (i = 0; i < migrate_item->services_list->num_services; i++) {
2519
2528
migrate_item->services_list->services[i] = data_buf_offset;
2520
data_buf_offset += __tunnel_channel_send_service_migrate_data(channel,
2529
data_buf_offset += __tunnel_channel_marshall_service_migrate_data(tunnel_channel, m,
2521
2530
migrate_item->services + i,
2522
2531
data_buf_offset);
2526
2535
migrate_data->sockets_list = data_buf_offset;
2527
red_channel_add_buf(&channel->base, migrate_item->sockets_list,
2536
spice_marshaller_add_ref(m, (uint8_t*)migrate_item->sockets_list,
2528
2537
migrate_item->sockets_list_size);
2529
2538
data_buf_offset += migrate_item->sockets_list_size;
2531
2540
for (i = 0; i < migrate_item->sockets_list->num_sockets; i++) {
2532
2541
migrate_item->sockets_list->sockets[i] = data_buf_offset;
2533
data_buf_offset += __tunnel_channel_send_socket_migrate_data(channel,
2542
data_buf_offset += __tunnel_channel_marshall_socket_migrate_data(tunnel_channel, m,
2534
2543
migrate_item->sockets_data + i,
2535
2544
data_buf_offset);
2538
red_channel_begin_send_message(&channel->base);
2541
static void tunnel_channel_send_init(TunnelChannel *channel, PipeItem *item)
2548
static void tunnel_channel_marshall_init(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2550
TunnelChannelClient *channel;
2553
channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2545
2554
channel->send_data.u.init.max_socket_data_size = MAX_SOCKET_DATA_SIZE;
2546
2555
channel->send_data.u.init.max_num_of_sockets = MAX_SOCKETS_NUM;
2548
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_INIT, item);
2549
red_channel_add_buf(&channel->base, &channel->send_data.u.init, sizeof(SpiceMsgTunnelInit));
2551
red_channel_begin_send_message(&channel->base);
2557
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_INIT, item);
2558
spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.init, sizeof(SpiceMsgTunnelInit));
2554
static void tunnel_channel_send_service_ip_map(TunnelChannel *channel, PipeItem *item)
2561
static void tunnel_channel_marshall_service_ip_map(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2563
TunnelChannelClient *tunnel_channel;
2556
2564
TunnelService *service = SPICE_CONTAINEROF(item, TunnelService, pipe_item);
2558
channel->send_data.u.service_ip.service_id = service->id;
2559
channel->send_data.u.service_ip.virtual_ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
2566
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2567
tunnel_channel->send_data.u.service_ip.service_id = service->id;
2568
tunnel_channel->send_data.u.service_ip.virtual_ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
2561
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SERVICE_IP_MAP, item);
2562
red_channel_add_buf(&channel->base, &channel->send_data.u.service_ip,
2570
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SERVICE_IP_MAP, item);
2571
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.service_ip,
2563
2572
sizeof(SpiceMsgTunnelServiceIpMap));
2564
red_channel_add_buf(&channel->base, &service->virt_ip.s_addr, sizeof(SpiceTunnelIPv4));
2565
red_channel_begin_send_message(&channel->base);
2573
spice_marshaller_add_ref(m, (uint8_t*)&service->virt_ip.s_addr, sizeof(SpiceTunnelIPv4));
2568
static void tunnel_channel_send_socket_open(TunnelChannel *channel, PipeItem *item)
2576
static void tunnel_channel_marshall_socket_open(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2578
TunnelChannelClient *tunnel_channel;
2570
2579
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
2571
2580
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2573
channel->send_data.u.socket_open.connection_id = sckt->connection_id;
2574
channel->send_data.u.socket_open.service_id = sckt->far_service->id;
2575
channel->send_data.u.socket_open.tokens = SOCKET_WINDOW_SIZE;
2582
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2583
tunnel_channel->send_data.u.socket_open.connection_id = sckt->connection_id;
2584
tunnel_channel->send_data.u.socket_open.service_id = sckt->far_service->id;
2585
tunnel_channel->send_data.u.socket_open.tokens = SOCKET_WINDOW_SIZE;
2577
2587
sckt->in_data.client_total_num_tokens = SOCKET_WINDOW_SIZE;
2578
2588
sckt->in_data.num_tokens = 0;
2579
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_OPEN, item);
2580
red_channel_add_buf(&channel->base, &channel->send_data.u.socket_open,
2581
sizeof(channel->send_data.u.socket_open));
2583
red_channel_begin_send_message(&channel->base);
2589
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_OPEN, item);
2590
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_open,
2591
sizeof(tunnel_channel->send_data.u.socket_open));
2584
2592
#ifdef DEBUG_NETWORK
2585
2593
PRINT_SCKT(sckt);
2589
static void tunnel_channel_send_socket_fin(TunnelChannel *channel, PipeItem *item)
2597
static void tunnel_channel_marshall_socket_fin(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2599
TunnelChannelClient *tunnel_channel;
2591
2600
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
2592
2601
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2594
2603
ASSERT(!sckt->out_data.ready_chunks_queue.head);
2605
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2596
2606
if (sckt->out_data.process_queue->head) {
2597
2607
red_printf("socket sent FIN but there are still buffers in outgoing process queue"
2598
2608
"(local_port=%d, service_id=%d)",
2599
2609
ntohs(sckt->local_port), sckt->far_service->id);
2602
channel->send_data.u.socket_fin.connection_id = sckt->connection_id;
2604
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_FIN, item);
2605
red_channel_add_buf(&channel->base, &channel->send_data.u.socket_fin,
2606
sizeof(channel->send_data.u.socket_fin));
2608
red_channel_begin_send_message(&channel->base);
2612
tunnel_channel->send_data.u.socket_fin.connection_id = sckt->connection_id;
2614
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_FIN, item);
2615
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_fin,
2616
sizeof(tunnel_channel->send_data.u.socket_fin));
2610
2617
#ifdef DEBUG_NETWORK
2611
2618
PRINT_SCKT(sckt);
2615
static void tunnel_channel_send_socket_close(TunnelChannel *channel, PipeItem *item)
2622
static void tunnel_channel_marshall_socket_close(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2624
TunnelChannelClient *tunnel_channel;
2617
2625
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
2618
2626
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2628
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2620
2629
// can happen when it is a forced close
2621
2630
if (sckt->out_data.ready_chunks_queue.head) {
2622
2631
red_printf("socket closed but there are still buffers in outgoing ready queue"
2631
2640
ntohs(sckt->local_port), sckt->far_service->id);
2634
channel->send_data.u.socket_close.connection_id = sckt->connection_id;
2636
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_CLOSE, item);
2637
red_channel_add_buf(&channel->base, &channel->send_data.u.socket_close,
2638
sizeof(channel->send_data.u.socket_close));
2640
red_channel_begin_send_message(&channel->base);
2643
tunnel_channel->send_data.u.socket_close.connection_id = sckt->connection_id;
2645
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_CLOSE, item);
2646
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_close,
2647
sizeof(tunnel_channel->send_data.u.socket_close));
2642
2648
#ifdef DEBUG_NETWORK
2643
2649
PRINT_SCKT(sckt);
2647
static void tunnel_channel_send_socket_closed_ack(TunnelChannel *channel, PipeItem *item)
2653
static void tunnel_channel_marshall_socket_closed_ack(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2655
TunnelChannelClient *tunnel_channel;
2649
2656
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
2650
2657
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2652
channel->send_data.u.socket_close_ack.connection_id = sckt->connection_id;
2659
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2660
tunnel_channel->send_data.u.socket_close_ack.connection_id = sckt->connection_id;
2654
2662
// pipe item is null because we free the sckt.
2655
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK, NULL);
2656
red_channel_add_buf(&channel->base, &channel->send_data.u.socket_close_ack,
2657
sizeof(channel->send_data.u.socket_close_ack));
2659
red_channel_begin_send_message(&channel->base);
2663
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK, NULL);
2664
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_close_ack,
2665
sizeof(tunnel_channel->send_data.u.socket_close_ack));
2661
2666
#ifdef DEBUG_NETWORK
2662
2667
PRINT_SCKT(sckt);
2665
2670
ASSERT(sckt->client_waits_close_ack && (sckt->client_status == CLIENT_SCKT_STATUS_CLOSED));
2666
tunnel_worker_free_socket(channel->worker, sckt);
2667
if (CHECK_TUNNEL_ERROR(channel)) {
2668
tunnel_shutdown(channel->worker);
2671
tunnel_worker_free_socket(tunnel_channel->worker, sckt);
2672
if (CHECK_TUNNEL_ERROR(tunnel_channel)) {
2673
tunnel_shutdown(tunnel_channel->worker);
2672
static void tunnel_channel_send_socket_token(TunnelChannel *channel, PipeItem *item)
2677
static void tunnel_channel_marshall_socket_token(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2679
TunnelChannelClient *tunnel_channel;
2674
2680
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, token_pipe_item);
2675
2681
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2677
2683
/* notice that the num of tokens sent can be > SOCKET_TOKENS_TO_SEND, since
2678
2684
the sending is performed after the pipe item was pushed */
2680
channel->send_data.u.socket_token.connection_id = sckt->connection_id;
2686
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2687
tunnel_channel->send_data.u.socket_token.connection_id = sckt->connection_id;
2682
2689
if (sckt->in_data.num_tokens > 0) {
2683
channel->send_data.u.socket_token.num_tokens = sckt->in_data.num_tokens;
2690
tunnel_channel->send_data.u.socket_token.num_tokens = sckt->in_data.num_tokens;
2685
2692
ASSERT(!sckt->in_data.client_total_num_tokens && !sckt->in_data.ready_chunks_queue.head);
2686
channel->send_data.u.socket_token.num_tokens = SOCKET_TOKENS_TO_SEND_FOR_PROCESS;
2693
tunnel_channel->send_data.u.socket_token.num_tokens = SOCKET_TOKENS_TO_SEND_FOR_PROCESS;
2688
sckt->in_data.num_tokens -= channel->send_data.u.socket_token.num_tokens;
2689
sckt->in_data.client_total_num_tokens += channel->send_data.u.socket_token.num_tokens;
2695
sckt->in_data.num_tokens -= tunnel_channel->send_data.u.socket_token.num_tokens;
2696
sckt->in_data.client_total_num_tokens += tunnel_channel->send_data.u.socket_token.num_tokens;
2690
2697
ASSERT(sckt->in_data.client_total_num_tokens <= SOCKET_WINDOW_SIZE);
2692
red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_TOKEN, item);
2693
red_channel_add_buf(&channel->base, &channel->send_data.u.socket_token,
2694
sizeof(channel->send_data.u.socket_token));
2696
red_channel_begin_send_message(&channel->base);
2699
red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_TOKEN, item);
2700
spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_token,
2701
sizeof(tunnel_channel->send_data.u.socket_token));
2699
static void tunnel_channel_send_socket_out_data(TunnelChannel *channel, PipeItem *item)
2704
static void tunnel_channel_marshall_socket_out_data(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
2706
TunnelChannelClient *tunnel_channel;
2707
tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannelClient, base);
2701
2708
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, data_pipe_item);
2702
2709
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
2703
2710
ReadyTunneledChunk *chunk;
2803
2808
if (((sckt->slirp_status == SLIRP_SCKT_STATUS_OPEN) ||
2804
2809
(sckt->slirp_status == SLIRP_SCKT_STATUS_SHUTDOWN_RECV)) &&
2805
!sckt->in_slirp_send && !worker->channel->mig_inprogress) {
2810
!sckt->in_slirp_send && !worker->channel_client->mig_inprogress) {
2806
2811
// for cases that slirp couldn't write whole it data to our socket buffer
2807
2812
net_slirp_socket_can_send_notify(sckt->slirp_sckt);
2811
static void tunnel_channel_send_item(RedChannel *channel, PipeItem *item)
2816
static void tunnel_channel_send_item(RedChannelClient *rcc, PipeItem *item)
2813
TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
2818
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
2815
red_channel_reset_send_data(channel);
2816
2820
switch (item->type) {
2817
case PIPE_ITEM_TYPE_SET_ACK:
2818
tunnel_channel_send_set_ack(tunnel_channel, item);
2820
2821
case PIPE_ITEM_TYPE_TUNNEL_INIT:
2821
tunnel_channel_send_init(tunnel_channel, item);
2822
tunnel_channel_marshall_init(rcc, m, item);
2823
2824
case PIPE_ITEM_TYPE_SERVICE_IP_MAP:
2824
tunnel_channel_send_service_ip_map(tunnel_channel, item);
2825
tunnel_channel_marshall_service_ip_map(rcc, m, item);
2826
2827
case PIPE_ITEM_TYPE_SOCKET_OPEN:
2827
tunnel_channel_send_socket_open(tunnel_channel, item);
2828
tunnel_channel_marshall_socket_open(rcc, m, item);
2829
2830
case PIPE_ITEM_TYPE_SOCKET_DATA:
2830
tunnel_channel_send_socket_out_data(tunnel_channel, item);
2831
tunnel_channel_marshall_socket_out_data(rcc, m, item);
2832
2833
case PIPE_ITEM_TYPE_SOCKET_FIN:
2833
tunnel_channel_send_socket_fin(tunnel_channel, item);
2834
tunnel_channel_marshall_socket_fin(rcc, m, item);
2835
2836
case PIPE_ITEM_TYPE_SOCKET_CLOSE:
2836
tunnel_channel_send_socket_close(tunnel_channel, item);
2837
tunnel_channel_marshall_socket_close(rcc, m, item);
2838
2839
case PIPE_ITEM_TYPE_SOCKET_CLOSED_ACK:
2839
tunnel_channel_send_socket_closed_ack(tunnel_channel, item);
2840
tunnel_channel_marshall_socket_closed_ack(rcc, m, item);
2841
2842
case PIPE_ITEM_TYPE_SOCKET_TOKEN:
2842
tunnel_channel_send_socket_token(tunnel_channel, item);
2843
tunnel_channel_marshall_socket_token(rcc, m, item);
2844
2845
case PIPE_ITEM_TYPE_MIGRATE:
2845
tunnel_channel_send_migrate(tunnel_channel, item);
2846
tunnel_channel_marshall_migrate(rcc, m, item);
2847
2848
case PIPE_ITEM_TYPE_MIGRATE_DATA:
2848
tunnel_channel_send_migrate_data(tunnel_channel, item);
2849
tunnel_channel_marshall_migrate_data(rcc, m, item);
2851
2852
red_error("invalid pipe item type");
2854
red_channel_client_begin_send_message(rcc);
2855
2857
/* param item_pushed: distinguishes between a pipe item that was pushed for sending, and
2856
2858
a pipe item that is still in the pipe and is released due to disconnection.
2857
2859
see red_pipe_item_clear */
2858
static void tunnel_channel_release_pipe_item(RedChannel *channel, PipeItem *item, int item_pushed)
2860
static void tunnel_channel_release_pipe_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
2860
2862
if (!item) { // e.g. when acking closed socket
2863
2865
switch (item->type) {
2864
case PIPE_ITEM_TYPE_SET_ACK:
2865
2866
case PIPE_ITEM_TYPE_TUNNEL_INIT:
3390
3393
/* don't call disconnect from functions that might be called by slirp
3391
3394
since it closes all its sockets and slirp is not aware of it */
3392
static void tunnel_channel_disconnect(RedChannel *channel)
3395
static void tunnel_channel_on_disconnect(RedChannel *channel)
3394
TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
3395
3397
TunnelWorker *worker;
3396
3398
if (!channel) {
3399
3401
red_printf("");
3400
worker = tunnel_channel->worker;
3402
worker = (TunnelWorker *)channel->data;
3402
3404
tunnel_worker_disconnect_slirp(worker);
3404
3406
tunnel_worker_clear_routed_network(worker);
3405
red_channel_destroy(channel);
3406
worker->channel = NULL;
3407
worker->channel_client = NULL;
3410
// TODO - not MC friendly, remove
3411
static void tunnel_channel_client_on_disconnect(RedChannelClient *rcc)
3413
tunnel_channel_on_disconnect(rcc->channel);
3409
3416
/* interface for reds */
3411
static void on_new_tunnel_channel(TunnelChannel *channel)
3418
static void on_new_tunnel_channel(TunnelChannelClient *tcc)
3413
red_channel_pipe_add_type(&channel->base, PIPE_ITEM_TYPE_SET_ACK);
3420
red_channel_client_push_set_ack(&tcc->base);
3415
if (channel->base.migrate) {
3416
channel->expect_migrate_data = TRUE;
3422
if (tcc->base.channel->migrate) {
3423
tcc->expect_migrate_data = TRUE;
3418
red_channel_init_outgoing_messages_window(&channel->base);
3419
red_channel_pipe_add_type(&channel->base, PIPE_ITEM_TYPE_TUNNEL_INIT);
3425
red_channel_init_outgoing_messages_window(tcc->base.channel);
3426
red_channel_client_pipe_add_type(&tcc->base, PIPE_ITEM_TYPE_TUNNEL_INIT);
3423
static void handle_tunnel_channel_link(Channel *channel, RedsStream *stream, int migration,
3424
int num_common_caps, uint32_t *common_caps, int num_caps,
3430
static void tunnel_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
3434
static void handle_tunnel_channel_link(RedChannel *channel, RedClient *client,
3435
RedsStream *stream, int migration,
3436
int num_common_caps,
3437
uint32_t *common_caps, int num_caps,
3425
3438
uint32_t *caps)
3427
TunnelChannel *tunnel_channel;
3440
TunnelChannelClient *tcc;
3428
3441
TunnelWorker *worker = (TunnelWorker *)channel->data;
3429
if (worker->channel) {
3430
tunnel_channel_disconnect(&worker->channel->base);
3434
(TunnelChannel *)red_channel_create(sizeof(*tunnel_channel), stream, worker->core_interface,
3436
tunnel_channel_config_socket,
3437
tunnel_channel_disconnect,
3438
tunnel_channel_handle_message,
3439
tunnel_channel_alloc_msg_rcv_buf,
3440
tunnel_channel_release_msg_rcv_buf,
3441
tunnel_channel_send_item,
3442
tunnel_channel_release_pipe_item);
3444
if (!tunnel_channel) {
3449
tunnel_channel->worker = worker;
3450
tunnel_channel->worker->channel = tunnel_channel;
3443
if (worker->channel_client) {
3444
red_error("tunnel does not support multiple client");
3447
tcc = (TunnelChannelClient*)red_channel_client_create(sizeof(TunnelChannelClient),
3448
channel, client, stream,
3451
tcc->worker = worker;
3452
tcc->worker->channel_client = tcc;
3451
3453
net_slirp_set_net_interface(&worker->tunnel_interface.base);
3453
on_new_tunnel_channel(tunnel_channel);
3456
static void handle_tunnel_channel_shutdown(struct Channel *channel)
3458
tunnel_channel_disconnect(&((TunnelWorker *)channel->data)->channel->base);
3461
static void handle_tunnel_channel_migrate(struct Channel *channel)
3455
on_new_tunnel_channel(tcc);
3458
static void handle_tunnel_channel_client_migrate(RedChannelClient *rcc)
3460
TunnelChannelClient *tunnel_channel;
3463
3461
#ifdef DEBUG_NETWORK
3464
3462
red_printf("TUNNEL_DBG: MIGRATE STARTED");
3466
TunnelChannel *tunnel_channel = ((TunnelWorker *)channel->data)->channel;
3464
tunnel_channel = (TunnelChannelClient *)rcc;
3465
ASSERT(tunnel_channel == tunnel_channel->worker->channel_client);
3467
3466
tunnel_channel->mig_inprogress = TRUE;
3468
3467
net_slirp_freeze();
3469
red_channel_pipe_add_type(&tunnel_channel->base, PIPE_ITEM_TYPE_MIGRATE);
3468
red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_MIGRATE);
3471
static void red_tunnel_channel_create(TunnelWorker *worker)
3473
RedChannel *channel;
3474
ChannelCbs channel_cbs;
3475
ClientCbs client_cbs = {0,};
3477
channel_cbs.config_socket = tunnel_channel_config_socket;
3478
channel_cbs.on_disconnect = tunnel_channel_client_on_disconnect;
3479
channel_cbs.alloc_recv_buf = tunnel_channel_alloc_msg_rcv_buf;
3480
channel_cbs.release_recv_buf = tunnel_channel_release_msg_rcv_buf;
3481
channel_cbs.hold_item = tunnel_channel_hold_pipe_item;
3482
channel_cbs.send_item = tunnel_channel_send_item;
3483
channel_cbs.release_item = tunnel_channel_release_pipe_item;
3484
channel_cbs.handle_migrate_flush_mark = tunnel_channel_handle_migrate_mark;
3485
channel_cbs.handle_migrate_data = tunnel_channel_handle_migrate_data;
3486
channel_cbs.handle_migrate_data_get_serial = tunnel_channel_handle_migrate_data_get_serial;
3488
channel = red_channel_create(sizeof(RedChannel),
3489
worker->core_interface,
3490
SPICE_CHANNEL_TUNNEL, 0,
3491
FALSE, // TODO: handle migration=TRUE
3493
tunnel_channel_handle_message,
3499
client_cbs.connect = handle_tunnel_channel_link;
3500
client_cbs.migrate = handle_tunnel_channel_client_migrate;
3501
red_channel_register_client_cbs(channel, &client_cbs);
3503
worker->channel = channel;
3504
red_channel_set_data(channel, worker);
3505
reds_register_channel(worker->channel);