| 1266 | } |
| 1267 | |
| 1268 | int MtFrame::recv(int fd, void *buf, int len, int flags, int timeout) |
| 1269 | { |
| 1270 | MtFrame* mtframe = MtFrame::Instance(); |
| 1271 | utime64_t start = mtframe->GetLastClock(); |
| 1272 | MicroThread* thread = mtframe->GetActiveThread(); |
| 1273 | utime64_t now = 0; |
| 1274 | |
| 1275 | if(fd<0 || !buf || len<1) |
| 1276 | { |
| 1277 | errno = EINVAL; |
| 1278 | MTLOG_ERROR("recv failed, errno: %d (%m)", errno); |
| 1279 | return -10; |
| 1280 | } |
| 1281 | |
| 1282 | if (timeout <= -1) |
| 1283 | { |
| 1284 | timeout = 0x7fffffff; |
| 1285 | } |
| 1286 | |
| 1287 | while (true) |
| 1288 | { |
| 1289 | now = mtframe->GetLastClock(); |
| 1290 | if ((int)(now - start) > timeout) |
| 1291 | { |
| 1292 | errno = ETIME; |
| 1293 | return -1; |
| 1294 | } |
| 1295 | |
| 1296 | KqueuerObj epfd; |
| 1297 | epfd.SetOsfd(fd); |
| 1298 | epfd.EnableInput(); |
| 1299 | epfd.SetOwnerThread(thread); |
| 1300 | if (!mtframe->KqueueSchedule(NULL, &epfd, timeout)) |
| 1301 | { |
| 1302 | MTLOG_DEBUG("epoll schedule failed, errno: %d", errno); |
| 1303 | return -2; |
| 1304 | } |
| 1305 | |
| 1306 | mt_hook_syscall(recv); |
| 1307 | int n = ff_hook_recv(fd, buf, len, flags); |
| 1308 | if (n < 0) |
| 1309 | { |
| 1310 | if (errno == EINTR) { |
| 1311 | continue; |
| 1312 | } |
| 1313 | |
| 1314 | if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) |
| 1315 | { |
| 1316 | MTLOG_ERROR("recv failed, errno: %d", errno); |
| 1317 | return -3; |
| 1318 | } |
| 1319 | } |
| 1320 | else |
| 1321 | { |
| 1322 | return n; |
| 1323 | } |
| 1324 | } |
| 1325 | |