| 1092 | } |
| 1093 | |
| 1094 | static int udp_close(URLContext *h) |
| 1095 | { |
| 1096 | UDPContext *s = h->priv_data; |
| 1097 | |
| 1098 | #if HAVE_PTHREAD_CANCEL |
| 1099 | // Request close once writing is finished |
| 1100 | if (s->thread_started && !(h->flags & AVIO_FLAG_READ)) { |
| 1101 | pthread_mutex_lock(&s->mutex); |
| 1102 | s->close_req = 1; |
| 1103 | pthread_cond_signal(&s->cond); |
| 1104 | pthread_mutex_unlock(&s->mutex); |
| 1105 | } |
| 1106 | #endif |
| 1107 | |
| 1108 | if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) |
| 1109 | udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr, |
| 1110 | (struct sockaddr *)&s->local_addr_storage, h); |
| 1111 | #if HAVE_PTHREAD_CANCEL |
| 1112 | if (s->thread_started) { |
| 1113 | int ret; |
| 1114 | // Cancel only read, as write has been signaled as success to the user |
| 1115 | if (h->flags & AVIO_FLAG_READ) { |
| 1116 | #ifdef _WIN32 |
| 1117 | /* recvfrom() is not a cancellation point for win32, so we shutdown |
| 1118 | * the socket and abort pending IO, subsequent recvfrom() calls |
| 1119 | * will fail with WSAESHUTDOWN causing the thread to exit. */ |
| 1120 | shutdown(s->udp_fd, SD_RECEIVE); |
| 1121 | CancelIoEx((HANDLE)(SOCKET)s->udp_fd, NULL); |
| 1122 | #else |
| 1123 | pthread_cancel(s->circular_buffer_thread); |
| 1124 | #endif |
| 1125 | } |
| 1126 | ret = pthread_join(s->circular_buffer_thread, NULL); |
| 1127 | if (ret != 0) |
| 1128 | av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", strerror(ret)); |
| 1129 | pthread_mutex_destroy(&s->mutex); |
| 1130 | pthread_cond_destroy(&s->cond); |
| 1131 | } |
| 1132 | #endif |
| 1133 | closesocket(s->udp_fd); |
| 1134 | av_fifo_freep2(&s->rx_fifo); |
| 1135 | av_fifo_freep2(&s->tx_fifo); |
| 1136 | ff_ip_reset_filters(&s->filters); |
| 1137 | return 0; |
| 1138 | } |
| 1139 | |
| 1140 | const URLProtocol ff_udp_protocol = { |
| 1141 | .name = "udp", |
nothing calls this directly
no test coverage detected