aboutsummaryrefslogtreecommitdiff
path: root/assets/blender/mbb/prellbock.uv.png
blob: 77307533fe09f1f514ab78bf617b3e34e603d086 (plain)
ofshex dumpascii
0000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 40 00 00 00 40 08 06 00 00 00 aa 69 71 .PNG........IHDR...@...@......iq
0020 de 00 00 00 09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 9a 9c 18 00 00 00 5c 74 45 58 74 46 69 .....pHYs................\tEXtFi
0040 6c 65 00 2f 68 6f 6d 65 2f 6d 6f 72 69 74 7a 2f 5f 2e 6d 69 6e 65 74 65 73 74 2f 6d 6f 64 73 2f le./home/moritz/_.minetest/mods/
0060 6d 6f 6e 6f 73 5f 6d 6f 64 73 5f 6d 70 2f 61 64 76 74 72 61 69 6e 73 2f 6d 6f 64 65 6c 73 2f 62 monos_mods_mp/advtrains/models/b
0080 6c 65 6e 64 65 72 2f 6d 62 62 2f 70 72 65 6c 6c 62 6f 63 6b 2e 62 6c 65 6e 64 90 b1 da 30 00 00 lender/mbb/prellbock.blend...0..
00a0 00 18 74 45 58 74 44 61 74 65 00 32 30 31 36 2f 30 39 2f 31 32 20 31 32 3a 33 39 3a 32 33 05 5a ..tEXtDate.2016/09/12.12:39:23.Z
00c0 86 bc 00 00 00 10 74 45 58 74 54 69 6d 65 00 30 30 3a 30 30 3a 30 30 3a 30 31 ec c3 26 c2 00 00 ......tEXtTime.00:00:00:01..&...
00e0 00 07 74 45 58 74 46 72 61 6d 65 00 31 af 92 b4 26 00 00 00 12 74 45 58 74 43 61 6d 65 72 61 00 ..tEXtFrame.1...&....tEXtCamera.
0100 75 76 5f 74 65 6d 70 5f 63 61 6d 71 4e bb ca 00 00 00 0d 74 45 58 74 53 63 65 6e 65 00 75 76 5f uv_temp_camqN......tEXtScene.uv_
0120 74 65 6d 70 d8 0d 1b 8f 00 00 00 13 74 45 58 74 52 65 6e 64 65 72 54 69 6d 65 00 30 30 3a 30 30 temp........tEXtRenderTime.00:00
0140 2e 30 33 39 3e 0f fb 00 00 0e 63 49 44 41 54 78 01 ed 9b 79 70 d5 d5 15 c7 f3 de cb be 90 00 81 .039>.....cIDATx...yp...........
0160 00 21 40 48 d8 37 d9 21 05 a4 80 ad 80 d3 41 28 15 6d 15 04 85 0e 60 67 10 45 fe 90 d1 a6 08 d8 .!@H.7.!......A(.m....`g.E......
0180 19 40 ea c8 26 1d ab 8c d5 42 ad 30 65 19 40 44 02 c8 22 fb 0e 86 25 6c 12 08 84 44 20 04 f2 de .@..&....B.0e.@D.."...%l...D....
01a0 eb e7 fb e3 fd 9e ef 85 10 7e 09 79 e9 4c e4 ce dc 77 7f bf df 5d cf 72 cf 39 f7 dc f3 82 82 aa .........~.y.L...w...].r.9......
01c0 76 0a 01 3c 7b 09 d9 b1 6e dd 3a 7b 8d 1a 35 82 6c 55 18 fe 81 c0 36 8d ec 8c 8d 8d bd 4d b2 17 v..<{...n.:{..5.lU....6......M..
01e0 15 15 d9 ee dc b9 13 52 bd 7a f5 82 c4 c4 c4 1b 3d 7b f6 9c 10 5c 85 11 10 0d 6c 6d 87 0e 1d ba .......R.z......={...\....lm....
0200 f1 99 67 9e f9 d4 ed 76 db f6 ef df df 7a f3 e6 cd 4f 00 f8 c6 f4 f4 f4 3f 1d 3c 78 b0 51 55 46 ..g....v.....z...O......?.<x.QUF
0220 80 41 db ba 75 eb 66 0d 1a 34 e8 80 cb e5 0a 2a 2c 2c 0c de bd 7b 77 b7 66 cd 9a 1d 8b 88 88 08 .A..u.f..4.....*,,...{w.f.......
0240 2a 28 28 70 55 79 04 ec db b7 af cb cb 2f bf 1c 0b 02 ec 97 2f 5f ae 7b f2 e4 c9 e4 25 4b 96 fc *((pUy......./....../_.{....%K..
0260 1e e0 0d 04 55 79 04 68 cf 57 ab 56 ed 1a d0 b2 0b dc f6 b3 67 cf 26 c5 c4 c4 e4 45 47 47 07 5d ....Uy.h.W.V........g.&....EGG.]
0280 bf 7e 3d a8 ca 23 20 3f 3f 3f fc e8 d1 a3 4d 9c 4e a7 e3 e6 cd 9b d1 20 a0 3a d2 bf 8e 80 57 aa .~=..#.???....M.N........:....W.
02a0 f2 08 48 48 48 c8 6d db b6 ed 41 01 7b e1 c2 85 86 70 44 4c fd fa f5 b3 f5 ae 54 e5 11 f0 e3 8f ..HHH.m...A.{....pDL......T.....
02c0 3f c6 9c 3a 75 aa 29 32 c0 c1 be 8f 3c 7d fa 34 38 49 b8 78 17 fc 9f 01 02 ba 74 e9 b2 69 c6 8c ?..:u.)2....<}.48I.x......t..i..
02e0 19 f3 a5 05 96 2d 5b d6 01 c0 87 a3 16 17 63 08 75 41 2b 54 7d 0e d0 de 97 01 44 b6 f3 2c 63 48 .....-[.......c.uA+T}.....D..,cH
0300 5c ef 16 f0 4a 32 13 7f d6 a9 2c 32 a0 3a 98 72 56 32 b6 6c 9d 3a 75 72 ef dc b9 33 bf bc f3 da \...J2....,2.:.rV2.l.:ur...3....
0320 6c b6 20 87 c3 21 15 e8 e6 d9 cc de e1 ac 22 e0 29 7a 2c 40 9a 5e 15 2b 79 7b 07 f0 21 2c 2c ac l....!........".)z,@.^.+y{..!,,.
0340 08 23 a6 66 68 68 e8 d1 d1 a3 47 a7 af 5a b5 2a e3 dc b9 73 65 9e 11 35 18 07 02 eb 23 03 6c 39 .#.fhh....G..Z.*...se..5....#.l9
0360 39 39 35 38 13 84 fd f0 c3 0f b5 3d 96 a0 25 19 a0 03 d3 6f 5e 7a e9 a5 fc c9 93 27 ff a3 cc 2b 9958.......=..%....o^z.....'...+
0380 28 67 07 08 16 34 6d da b4 51 76 bb 3d ff da b5 6b 53 5a b6 6c b9 fb 95 57 5e 99 f6 c6 1b 6f e4 (g...4m..Qv.=...kSZ.l...W^....o.
03a0 95 65 c8 ed db b7 77 cb ca ca 4a 91 2c 00 78 f7 ae 5d bb 52 51 85 83 2d 5b 82 71 71 71 e3 31 1c .e....w...J.,.x..].RQ..-[.qqq.1.
03c0 06 1d 3b 76 2c e4 c3 0f 3f 7c 5a 03 95 65 01 1e b6 bb 5f 17 b1 a4 ea dc be 0d 3c 6c eb 64 e1 b5 ..;v,...?|Z..e...._.......<l.d..
03e0 9e 7f fe f9 2f ea d5 ab 97 b9 76 ed da c7 59 fc 82 a9 53 a7 fe e5 cd 37 df 3c e4 db be b4 e7 be ..../.....v...Y...S....7.<......
0400 7d fb ae 9d 34 69 d2 22 b5 59 b9 72 65 97 5a b5 6a 0d 1e 38 70 e0 17 8c 35 ed d6 ad 5b 0f e4 80 }...4i.".Y.re.Z.j..8p...5...[...
0420 5f 76 ed da b5 1f 66 e3 e9 86 0d 1b ba 65 40 c8 b4 14 50 c5 27 65 b0 30 51 cd 37 a9 1d d2 36 14 _v....f......e@...P.'e.0Q.7...6.
0440 cc 87 fa 7e 37 9f 41 a6 0d 16 d5 a9 cd 2f a9 5f 6e 6e 6e 0c c7 d6 9b eb d7 af 1f c6 81 66 37 c7 ...~7.A....../._nnn..........f7.
0460 d7 c3 c7 8f 1f 7f 6a d3 a6 4d 0b 4f 9c 38 31 34 25 25 e5 82 5f a7 fb bc 30 96 0b 02 de d2 d6 05 ......j..M.O.814%%.._...0.......
0480 8e 1b d2 02 1c 8f f3 05 bc 52 69 32 a0 35 f5 e9 6b d6 ac e9 d1 a4 49 93 7c 3a 9d e7 24 d5 e2 ea .........Ri2.5..k.....I.|:..$...
04a0 d5 ab d1 0c 6a 74 f6 fd 61 c1 6e 1d 38 7c bf 09 10 4c ce 08 8c 91 30 df ef e6 b3 f6 e5 99 33 67 ....jt..a.n.8|...L....0.......3g
04c0 a2 42 42 42 fc 30 17 1c 1c ec 06 31 be 9c 96 6a f6 81 08 37 e7 ce 9d 9b c0 bb 25 04 98 fd ee 57 .BBB.0.....1...j...7......%....W
04e0 96 86 80 b8 d4 d4 d4 36 1c 25 bf ed d0 a1 c3 31 84 d1 1d 01 2e a0 cc c1 f4 2c 20 cc ef be 75 6a .......6.%.....1.........,....uj
0500 23 84 14 e7 0a 4f 5f 39 26 34 b7 77 2c 7d d7 38 ec cd 12 91 75 e8 d0 a1 94 6f be f9 a6 d5 77 df #....O_9&4.w,}.8....u....o....w.
0520 7d 17 33 73 e6 4c bf 7e 9e 31 cb 55 94 86 80 94 bc bc bc 6a b5 6b d7 ce 13 60 08 a2 18 28 19 e5 }.3s.L.~.1.U.......j.k...`...(..
0540 0b a4 34 0b 1c 11 ab b2 f8 ec 6a 47 ff 68 b6 80 b6 8c 5f b5 80 87 63 34 96 df 77 bd 30 0f 78 f3 ..4.......jG.h...._...c4..w.0.x.
0560 e7 24 04 a1 13 4e 8a dc b3 67 4f 0c 4d dc ed da b5 b3 a3 21 ee e9 5b d2 07 b6 5f 38 d2 3f 42 84 .$...N...gO.M......!..[..._8.?B.
0580 60 8c 28 54 a2 93 39 62 ad 68 81 6e 2c d4 fd f5 d7 5f b7 60 2f 36 e5 24 15 e6 a1 b6 17 fb 5a 68 `.(T..9b.h.n,...._.`/6.$......Zh
05a0 76 76 76 34 0b f4 7e 33 17 21 e0 84 84 1b 37 6e b8 40 44 84 f9 5d a5 da 7b fa a8 0c ca cc cc 8c vvv4..~3.!....7n.@D..]..{.......
05c0 36 39 45 db 41 7a 5b ed 98 df 26 39 a1 67 33 21 94 dd c8 83 28 ab 08 d8 b2 65 4b 77 d4 68 92 84 69E.Az[...&9.g3!....(....eKw.h..
05e0 37 fb 3e 12 af 50 2a 6b 0a 7e a0 16 60 f1 ae 5e bd 7a ed 62 ef 17 20 45 ff 8d 00 91 83 d1 2f 69 7.>..P*k.~..`..^.z.b...E....../i
0600 d1 60 d8 5e 12 25 cd 86 aa 07 10 3f d9 60 d6 99 25 a7 b4 c4 92 b8 48 9c 22 2e 02 49 2e da d4 5a .`.^.%.....?.`..%.....H."..I...Z
0620 b1 62 45 1a 00 5d c0 26 c8 32 fb 96 52 5e 52 1d c8 ca 61 0b ef d6 b3 4e 83 10 2d a2 41 83 06 92 .bE..].&.2..R^R...a....N..-.A...
0640 1f 6d f5 ed be 5b 40 0b da bb 77 6f 43 ca 90 03 07 0e 34 8b 8a 8a 72 61 9c 14 8a 0b d4 d1 37 e9 .m...[@...woC.....4...ra......7.
0660 9b b4 80 28 ae ef 2a 3d 14 36 9e 91 bc 32 c5 7c bb 78 9f d5 8e 64 13 90 de 8f 9e 07 d5 c1 0d 2e ...(..*=.6...2.|.x...d..........
0680 95 b0 71 2c 3e bc 6a 54 1d 26 9f 29 de b6 84 77 c3 d8 87 da 51 a8 d3 54 e6 b0 43 f5 08 90 10 cf ..q,>.jT.&.)...w....Q..T..C.....
06a0 69 b0 06 9c 26 0e bb 3f 02 18 70 26 12 3a 16 3d 7c 8c 05 3c 86 fe 0c 02 93 b9 00 eb 2b 9d 8d 79 i...&..?..p&.:.=|..<........+..y
06c0 45 29 a4 b6 77 4f c3 6e 76 51 4e 95 e2 0e 8f 2c 28 51 15 0a 79 b8 aa 4a 94 23 ea 4e 5d 18 f3 5f E)..wO.nvQN....,(Q..y..J.#.N].._
06e0 8e 8f 8f bf 8d 67 c7 ce 3c 6b 8c 49 2d fe 88 f5 21 40 08 f3 d8 91 47 da 8a 4e a9 42 01 af 74 5f .....g..<k.I-...!@....G..N.B..t_
0700 0e a0 ee 04 f9 fd ad 5b b7 8e 78 e1 85 17 76 c1 76 c3 a0 40 3c 2a ea 1e 4a 89 e2 26 f5 35 a8 28 .......[..x...v.v..@<*..J..&.5.(
0720 16 1e 1e 7e 5b cf 42 80 a7 2c 91 05 d4 0f 0d 53 64 b6 33 1a f3 23 61 85 c9 5a 1d 81 b7 16 ee 2b ...~[.B..,.....Sd.3..#a..Z.....+
0740 c8 c8 c8 a8 0b f0 af 51 b5 dc 6c 63 a5 c4 88 3a d7 bb 77 ef 35 e2 40 ec 07 c9 b2 48 9c a2 fb 39 .......Q..lc...:..w.5.@....H...9
0760 0e 77 00 39 a5 22 40 e3 6f 43 40 25 7c fc f1 c7 a3 6b d6 ac 19 8d 2b f9 7d b4 c2 5d 0b a2 f4 d9 .w.9."@.oC@%|....k....+.}..]....
0780 05 54 89 00 97 de ed a7 5a 21 64 f6 ec d9 cf a2 fa 3a c2 fe 5f e1 cc 9c 40 6d e6 4f 2d ac 3d b1 .T......Z!d......:.._...@m.O-.=.
07a0 df 4f 8c 1f 3f fe 2b 80 b5 2d 5d ba f4 2a f0 b4 ec de bd fb f6 79 f3 e6 8d b0 82 00 cd b2 02 cc .O..?.+..-]..*.......y..........
07c0 b5 24 0f 78 eb ad b7 26 b0 77 ca 7b 22 94 5c 28 d4 7e b7 b2 74 38 cd 89 e5 17 87 fc 59 4a fb 49 .$.x...&.w.{".\(.~..t8......YJ.I
07e0 64 2b 88 f7 1d da d8 aa 20 ae 0d 88 7c 4a f3 02 43 33 54 60 02 77 03 8f 23 9c d5 d6 61 69 31 34 d+..........|J..C3T`.w..#...ai14
0800 ac 41 ee 45 7e 18 aa 4a 28 5d 26 5b 9d 93 a6 41 02 e2 18 59 5e dd b2 a6 76 74 78 cb d3 49 eb 96 .A.E~..J(]&[...A...Y^...vtx..I..
0820 26 d2 f6 65 77 39 6e 43 7d c9 a4 bf 92 1f a5 47 18 78 84 81 9f 31 06 ac 0a a4 28 70 f4 24 59 42 &..ew9nC}......G.x...1....(p.$YB
0840 c9 6a 9f f2 a0 d5 b5 78 f1 e2 1d a8 ad 2c 8c a7 f2 f4 2f 73 1f ab c0 f4 64 e4 8c fe fd fb e7 60 .j.....x.....,..../s....d......`
0860 94 48 95 95 79 a2 07 75 90 41 84 97 a6 5e 9d 3a 75 be ec d3 a7 cf ef de 79 e7 9d 7b 0c ae 07 8d .H..y..u.A...^.:u.......y..{....
0880 51 9e 7a ab 08 48 c3 b2 db fc c9 27 9f fc 9d bb f5 43 81 40 80 c6 c4 d5 35 f6 a3 8f 3e ba 0a 20 Q.z..H.....'.....C.@....5...>...
08a0 dd ca 03 4c 79 fa 58 46 00 83 6f 81 03 2e 72 20 ba 13 08 04 a0 9b dd 98 dd 89 98 bf 3b 98 2b ad ...Ly.XF..o...r.............;.+.
08c0 3c c0 04 b2 8f 16 24 be 77 63 09 8a 35 8d e7 8a 2c 39 76 17 c1 65 1a f7 5b b2 52 38 b9 09 b9 31 <.....$.wc..5...,9v..e..[.R8...1
08e0 39 a5 4d 9b 36 75 b1 24 79 ac d8 54 da 61 e8 9e 99 e6 cc 99 b3 ac 73 e7 ce 47 74 82 bb a7 b2 02 9.M.6u.$y..T.a........s..Gt.....
0900 3e e0 75 fe 2d e7 0e 13 ca ae 9c 00 97 26 27 27 e7 e0 89 0a e7 28 7b 76 c1 82 05 4f 10 ec 60 d8 >.u.-........&''.....({v...O..`.
0920 b0 15 30 9d 31 44 99 10 c0 f1 b8 2e 26 a4 23 10 08 60 0b b8 b8 bb 8f 67 55 39 1e e0 5c 1d 3b 76 ..0.1D......&.#..`.....gU9..\.;v
0940 3c b7 70 e1 c2 d7 56 af 5e dd 89 3b 89 17 01 5e 4e 99 ff 1f 02 d8 9f 35 75 ee 47 06 54 38 07 80 <.p...V.^..;...^N......5u.G.T8..
0960 00 27 37 3f 72 88 9a 2a c6 2d 4f 11 27 d0 f1 17 2f 5e 6c c0 21 46 67 79 b3 ce 83 a3 87 2f 2c 73 .'7?r..*.-O.'.../^l.!Fgy...../,s
0980 80 8e b7 5c 28 6c c6 4d b6 3f 10 42 50 a0 70 42 fb 23 27 40 2f 72 41 78 dc 95 2b 57 6a 8b e3 d8 ...\(l.M.?.BP.pB.#'@/rAx..+Wj...
09a0 ff 45 94 0f 0f 71 b1 11 2c 23 80 c5 d9 de 7b ef bd fe f3 e7 cf ef 17 88 2d a0 e3 2f ae ef 24 d6 .E...q..,#....{.........-../..$.
09c0 b7 cd b3 46 5b fb f6 ed 8f bc fb ee bb e9 38 66 db 73 c5 35 02 0f 74 b1 e5 3f fc ab 65 04 68 2a ...F[.........8f.s.5..t..?..e.h*
09e0 a8 11 8d a4 2e 92 73 e1 e1 a7 f6 1f 41 97 a1 b8 ac 7c c7 75 ef d8 b1 23 75 d8 b0 61 f3 14 db 03 ......s.....A....|.u...#u..a....
0a00 f0 32 0d ef 71 c7 f9 8f 52 f6 37 df 09 4b eb 9d 06 85 36 23 90 3e c3 bd b4 2b 10 1c a0 6d c5 65 .2..q...R.7..K....6#.>...+...m.e
0a20 e8 18 1f 43 48 02 4f 67 7a ed 7b ad 53 fe 84 03 e4 0a 4d 56 39 c0 88 b2 c0 3d 95 f6 fd f7 df cb ...CH.Ogz.{.S.....MV9....=......
0a40 c3 6a 15 71 96 17 2b 2d 40 fc 4e 03 3a c8 f9 21 4a cb 6b b9 93 1c d0 64 15 90 14 56 31 96 ac f6 .j.q..+-@.N.:..!J.k....d...V1...
0a60 d2 d3 56 fb d1 d4 72 12 a5 25 e5 36 90 ff 6b b9 d7 a3 86 8f 30 50 a1 18 10 6b 4b 2e 88 cd 2b 2b ..V...r..%.6..k.....0P...kK...++
0a80 07 23 ed 03 b1 a5 2c 21 a6 b8 10 9c 84 c1 f1 6c 64 64 64 a1 2e 40 b0 be 42 75 f8 91 da d3 79 9d .#....,!.......lddd..@..Bu....y.
0aa0 32 8c fb 81 eb d8 e6 7e f7 84 b4 2f 52 5b 66 b4 e1 2f e0 d2 e5 a7 bb 40 f5 d7 3b 76 84 03 63 ca 2......~.../R[f../.....@..;v..c.
0ac0 29 63 46 5a 84 ac 80 85 3b cc e7 fe e0 83 0f 32 b8 f9 4d 47 ef df 8d 5f b5 b4 f4 8a 69 54 1c 01 )cFZ....;......2..MG..._....iT..
0ae0 c9 d8 db 27 39 f6 ae 00 58 fb a2 45 8b c6 b6 6a d5 6a ef 91 23 47 1e 23 30 e1 14 3e fa d6 c3 87 ...'9...X..E...j.j..#G.#0..>....
0b00 0f ff 12 24 f8 b9 a9 85 1c 4f db 5d 3d 7a f4 d8 aa bb 40 73 79 20 a0 88 d0 94 01 20 28 5e ed 88 ...$.....O.]=z....@sy.......(^..
0b20 d6 b8 84 4e af cd e9 ef ca 80 01 03 56 eb ca 1d f5 3a 0e e0 3f a5 cf 3e b3 5f 65 95 62 73 dd e1 ...N........V....:..?..>._e.bs..
0b40 c9 e3 d3 99 dc 08 2a 15 40 31 a9 3d 05 15 3a 58 b4 cb 2c 45 3d ea 74 af e6 f0 cd 66 5b e9 72 28 ......*.@1.=..:X..,E=.t....f[.r(
0b60 ed 57 af 77 2e 4e 23 40 c4 2d 4e 74 e1 94 85 66 a9 31 cc f1 99 bb 2b 97 96 5d f1 0a e9 02 b4 52 .W.w.N#@.-Nt...f.1....+..].....R
0b80 53 2f 66 93 fa 91 1a 32 6f 75 55 1a df 08 2d 2f d2 77 02 0a 8c 52 5b c3 6c 6b 96 66 5b f3 bd a4 S/f....2ouU...-/.w...R[.lk.f[...
0ba0 52 d4 d7 77 d8 de 18 c7 6c 03 42 74 d3 64 d4 11 87 70 fb 35 12 25 9f 2a 27 49 f8 f4 c0 0f b7 8e R..w....l.Bt.d...p.5.%.*'I......
0bc0 4b c8 23 8a a5 17 b5 93 92 92 ce 8b 9a 87 0f 1f 6e cc 49 ec 04 6d 1a a7 a5 a5 5d 62 0b d4 87 55 K.#.............n.I..m....]b...U
0be0 4f ea e4 e6 bb 3c 51 91 8b d3 c6 a4 6c e4 c1 4d 5f 43 09 e4 38 09 a2 48 10 e7 08 89 5c b9 cb c0 O....<Q.....l..M_C..8..H....\...
0c00 71 35 6f de 3c 9a bb fb f3 92 07 d8 f9 cd f0 33 64 62 f2 c6 10 c0 70 0a 93 58 44 11 52 02 9e 24 q5o.<..........3db....p..XD.R..$
0c20 03 6c 78 5b 8e e3 ef 9b 40 20 c4 44 22 b2 ce be fe fa eb ff 62 c1 b6 31 63 c6 cc 58 be 7c f9 0c .lx[....@..D".......b..1c..X.|..
0c40 da bc 88 5c c8 64 7b f4 c1 59 99 9e 9c 9c ec 27 03 24 c8 88 c2 98 8e 33 73 f5 73 cf 3d b7 51 5b ...\.d{..Y.....'.$.....3s.s.=.Q[
0c60 c2 5c 39 36 be 93 3e 23 00 2e 8a ef 61 20 60 3d 75 4d 07 0f 1e 1c 32 71 e2 c4 cf f0 fe 86 8e 1a .\96..>#....a.`=uM....2q........
0c80 35 6a ce b8 71 e3 66 f3 5c 6d ec d8 b1 4f 53 5f 29 c0 6b 8d 06 02 10 78 0e a8 43 e1 0c 16 30 ca 5j..q.f.\m...OS_).k....x..C...0.
0ca0 b0 a6 02 a0 54 2f 8a c1 f9 c1 45 20 85 cf 21 8a 8a 52 5f 6f d2 37 f5 15 9b c3 1d d2 16 de 3a fa ....T/....E...!..R_o.7........:.
0cc0 19 81 54 8c a9 ad 63 9a b8 9a c7 08 7c 90 66 00 31 c6 3b e3 e8 40 e4 45 9e 77 90 00 3e 18 5a 40 ..T...c.....|.f.1.;..@.E.w..>.Z@
0ce0 8b d1 42 c4 da 3c 3b 3d 27 3e 85 be 98 94 d0 62 5d d4 17 01 90 51 ef bb 26 16 2e a4 a9 bf fc 7a ..B..<;='>.....b]....Q..&......z
0d00 1a c3 ec 17 a4 77 cf b8 c6 18 66 3f 8d a7 79 c4 69 aa d7 b8 9e ec 06 21 66 b3 80 97 42 80 8b 30 .....w....f?..y.i......!f...B..0
0d20 92 68 62 ef 9e 38 7f fe 7c 03 51 19 bd fc a4 64 00 de 9f 38 ea 05 8c 0d 3d dd 0d 16 ad ce 96 e8 .hb..8..|.Q....d...8....=.......
0d40 ab 7d ee bb 32 01 af 3a 24 78 37 24 7c a4 74 bc 59 2f a4 e0 e9 49 46 dd e9 8f 4b 72 74 8a 13 8a .}..2..:$x7$|.t.Y/...IF...Krt...
0d60 b8 b6 6e a1 79 34 1f 75 31 1b 36 6c 78 1c ea 6b 9b 18 44 31 fb 07 ba 34 26 c3 0b 93 88 4b ba 37 ..n.y4.u1.6lx..k..D1...4&....K.7
0d80 2e 28 45 61 c4 b2 10 c3 fd c4 7d 7a 22 0b 30 a8 09 80 35 58 74 3d 80 fc 05 94 d2 b6 f0 26 01 49 .(Ea......}z".0...5Xt=.......&.I
0da0 28 6d 92 62 88 d4 ae 38 02 08 4a 68 0a b5 0b d9 1a 91 74 d2 78 0e be b5 00 59 32 9e dc fc a7 07 (m.b...8..Jh......t.x....Y2.....
0dc0 39 5c a7 15 cf 5a 8f 8e bd 95 96 34 a1 8d d8 9f 23 53 a7 4e 9d 31 7d fa f4 71 c4 02 5d e4 6a 6a 9\...Z.....4....#S.N.1}..q..].jj
0de0 09 fa db fe ea ab af a6 a3 19 62 c5 e2 84 ad 67 40 ad 42 02 96 67 11 40 79 c5 77 85 00 6c 43 a0 ..........b....g@.B..g.@y.w..lC.
0e00 fd 19 77 d9 da 21 43 86 6c d2 bb 59 2f f9 30 6b d6 ac 3f 48 c2 4b 08 12 b9 2d ae 0a a2 ed 6a 04 ..w..!C.l..Y/.0k..?H.K...-....j.
0e20 df e7 20 3c 94 3c 9d 3f 38 7e 2a 41 b9 6d db b6 5f e1 78 31 bb 07 bc d4 42 7b 11 7c b4 11 a0 ce ...<.<.?8~*A.m.._.x1....B{.|....
0e40 c2 01 b5 00 dc 46 18 4c ae f6 28 54 ad 07 d5 b2 69 93 80 da ca 86 52 09 b4 cb 91 da f3 5d 99 84 .....F.L..(T....i.....R......]..
0e60 17 2a b3 1e da e1 2a cf ba 38 f1 22 40 fb 5a c1 94 42 0a 82 d6 85 67 59 1c 60 07 d1 0e 2c ca 5c .*....*..8."@.Z..B....gY.`...,.\
0e80 ed 7f 5c 61 89 4d 9b 36 15 d4 61 70 a3 02 22 64 94 19 9c 47 19 d0 24 0e c8 83 02 ff 21 0e 58 ac ..\a.M.6..ap.."d...G..$.....!.X.
0ea0 d7 1d 7d af 40 c4 d3 9a 55 66 6a eb d6 ad cf 01 5c 58 a3 46 8d ce 2b 80 b9 45 8b 16 27 60 75 bf ..}.@...Ufj.....\X.F..+..E..'`u.
0ec0 70 15 21 44 6d 01 22 0b 64 e6 f9 22 40 f2 01 27 4a 73 80 87 e3 0b c2 89 d9 b9 a9 88 4d de 6f 61 p.!Dm.".d.."@..'Js..........M.oa
0ee0 5e 67 a9 ad e2 f8 01 5c 37 42 fa 37 e3 1e 72 a5 00 cf 3c c6 9e 93 fd 3d 44 2f a4 b9 fd fa f5 2b ^g.....\7B.7..r...<....=D/.....+
0f00 e2 8e ee 9f c8 01 07 76 ff 74 c2 cd 57 71 c0 f9 35 06 d0 76 58 f8 ce db 6f bf 3d 95 28 ab dc bb .......v.t..Wq..5..vX...o.=.(...
0f20 cd ef fe 4a 60 aa 2d 7d 57 8e 1c 39 32 83 76 5e 21 28 2d 80 4f 7f 24 9c 15 a6 48 4d a2 b6 ce e0 ...J`.-}W..92.v^!(-.O.$...HM....
0f40 ed 4d 82 cb 2e 4c 99 32 e5 73 90 1a c6 9f 98 fe 86 b1 34 99 d1 f6 fb 8e 5b 19 cf 5e 56 f5 4c b6 .M...L.2.s........4.....[..^V.L.
0f60 90 bd 3e 18 ca 64 ea 1d ca b7 c2 3e bf 44 ac 5e 3c 21 aa 79 08 c1 3a 58 6c 07 25 f4 7c 17 a7 ed ..>..d.....>.D.^<!.y..:Xl.%.|...
0f80 a2 b6 b0 f5 15 72 b6 af 0c 50 1d 81 8a c9 94 e0 c9 ad 00 1d d9 0c c6 61 09 6e 38 c5 73 30 41 4b .....r...P.............a.n8.s0AK
0fa0 ad 40 44 4f c6 0c b8 0b cc 77 dd 7a fe 1f 73 7d d8 91 9e 73 0f 56 00 00 00 00 49 45 4e 44 ae 42 .@DO.....w.z..s}...s.V....IEND.B
0fc0 60 82 `.
etest Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "socket.h" // for select() #include "porting.h" // for sleep_ms(), get_sysinfo(), secure_rand_fill_buf() #include "httpfetch.h" #include <iostream> #include <sstream> #include <list> #include <map> #include <errno.h> #include "threading/event.h" #include "config.h" #include "exceptions.h" #include "debug.h" #include "log.h" #include "util/container.h" #include "util/thread.h" #include "version.h" #include "settings.h" #include "noise.h" Mutex g_httpfetch_mutex; std::map<unsigned long, std::queue<HTTPFetchResult> > g_httpfetch_results; PcgRandom g_callerid_randomness; HTTPFetchRequest::HTTPFetchRequest() { url = ""; caller = HTTPFETCH_DISCARD; request_id = 0; timeout = g_settings->getS32("curl_timeout"); connect_timeout = timeout; multipart = false; useragent = std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")"; } static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) { unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { MutexAutoLock lock(g_httpfetch_mutex); g_httpfetch_results[caller].push(fetch_result); } } static void httpfetch_request_clear(unsigned long caller); unsigned long httpfetch_caller_alloc() { MutexAutoLock lock(g_httpfetch_mutex); // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; for (unsigned long caller = discard + 1; caller != discard; ++caller) { std::map<unsigned long, std::queue<HTTPFetchResult> >::iterator it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) { verbosestream << "httpfetch_caller_alloc: allocating " << caller << std::endl; // Access element to create it g_httpfetch_results[caller]; return caller; } } FATAL_ERROR("httpfetch_caller_alloc: ran out of caller IDs"); return discard; } unsigned long httpfetch_caller_alloc_secure() { MutexAutoLock lock(g_httpfetch_mutex); // Generate random caller IDs and make sure they're not // already used or equal to HTTPFETCH_DISCARD // Give up after 100 tries to prevent infinite loop u8 tries = 100; unsigned long caller; do { caller = (((u64) g_callerid_randomness.next()) << 32) | g_callerid_randomness.next(); if (--tries < 1) { FATAL_ERROR("httpfetch_caller_alloc_secure: ran out of caller IDs"); return HTTPFETCH_DISCARD; } } while (g_httpfetch_results.find(caller) != g_httpfetch_results.end()); verbosestream << "httpfetch_caller_alloc_secure: allocating " << caller << std::endl; // Access element to create it g_httpfetch_results[caller]; return caller; } void httpfetch_caller_free(unsigned long caller) { verbosestream<<"httpfetch_caller_free: freeing " <<caller<<std::endl; httpfetch_request_clear(caller); if (caller != HTTPFETCH_DISCARD) { MutexAutoLock lock(g_httpfetch_mutex); g_httpfetch_results.erase(caller); } } bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) { MutexAutoLock lock(g_httpfetch_mutex); // Check that caller exists std::map<unsigned long, std::queue<HTTPFetchResult> >::iterator it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) return false; // Check that result queue is nonempty std::queue<HTTPFetchResult> &caller_results = it->second; if (caller_results.empty()) return false; // Pop first result fetch_result = caller_results.front(); caller_results.pop(); return true; } #if USE_CURL #include <curl/curl.h> /* USE_CURL is on: use cURL based httpfetch implementation */ static size_t httpfetch_writefunction( char *ptr, size_t size, size_t nmemb, void *userdata) { std::ostringstream *stream = (std::ostringstream*)userdata; size_t count = size * nmemb; stream->write(ptr, count); return count; } static size_t httpfetch_discardfunction( char *ptr, size_t size, size_t nmemb, void *userdata) { return size * nmemb; } class CurlHandlePool { std::list<CURL*> handles; public: CurlHandlePool() {} ~CurlHandlePool() { for (std::list<CURL*>::iterator it = handles.begin(); it != handles.end(); ++it) { curl_easy_cleanup(*it); } } CURL * alloc() { CURL *curl; if (handles.empty()) { curl = curl_easy_init(); if (curl == NULL) { errorstream<<"curl_easy_init returned NULL"<<std::endl; } } else { curl = handles.front(); handles.pop_front(); } return curl; } void free(CURL *handle) { if (handle) handles.push_back(handle); } }; class HTTPFetchOngoing { public: HTTPFetchOngoing(HTTPFetchRequest request, CurlHandlePool *pool); ~HTTPFetchOngoing(); CURLcode start(CURLM *multi); const HTTPFetchResult * complete(CURLcode res); const HTTPFetchRequest &getRequest() const { return request; }; const CURL *getEasyHandle() const { return curl; }; private: CurlHandlePool *pool; CURL *curl; CURLM *multi; HTTPFetchRequest request; HTTPFetchResult result; std::ostringstream oss; struct curl_slist *http_header; curl_httppost *post; }; HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *pool_): pool(pool_), curl(NULL), multi(NULL), request(request_), result(request_), oss(std::ios::binary), http_header(NULL), post(NULL) { curl = pool->alloc(); if (curl == NULL) { return; } // Set static cURL options curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1); std::string bind_address = g_settings->get("bind_address"); if (!bind_address.empty()) { curl_easy_setopt(curl, CURLOPT_INTERFACE, bind_address.c_str()); } #if LIBCURL_VERSION_NUM >= 0x071304 // Restrict protocols so that curl vulnerabilities in // other protocols don't affect us. // These settings were introduced in curl 7.19.4. long protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | CURLPROTO_FTPS; curl_easy_setopt(curl, CURLOPT_PROTOCOLS, protocols); curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, protocols); #endif // Set cURL options based on HTTPFetchRequest curl_easy_setopt(curl, CURLOPT_URL, request.url.c_str()); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, request.timeout); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, request.connect_timeout); if (request.useragent != "") curl_easy_setopt(curl, CURLOPT_USERAGENT, request.useragent.c_str()); // Set up a write callback that writes to the // ostringstream ongoing->oss, unless the data // is to be discarded if (request.caller == HTTPFETCH_DISCARD) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, httpfetch_discardfunction); curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL); } else { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, httpfetch_writefunction); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &oss); } // Set POST (or GET) data if (request.post_fields.empty() && request.post_data.empty()) { curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); } else if (request.multipart) { curl_httppost *last = NULL; for (StringMap::iterator it = request.post_fields.begin(); it != request.post_fields.end(); ++it) { curl_formadd(&post, &last, CURLFORM_NAMELENGTH, it->first.size(), CURLFORM_PTRNAME, it->first.c_str(), CURLFORM_CONTENTSLENGTH, it->second.size(), CURLFORM_PTRCONTENTS, it->second.c_str(), CURLFORM_END); } curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); // request.post_fields must now *never* be // modified until CURLOPT_HTTPPOST is cleared } else if (request.post_data.empty()) { curl_easy_setopt(curl, CURLOPT_POST, 1); std::string str; for (StringMap::iterator it = request.post_fields.begin(); it != request.post_fields.end(); ++it) { if (str != "") str += "&"; str += urlencode(it->first); str += "="; str += urlencode(it->second); } curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, str.size()); curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, str.c_str()); } else { curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.post_data.size()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.post_data.c_str()); // request.post_data must now *never* be // modified until CURLOPT_POSTFIELDS is cleared } // Set additional HTTP headers for (std::vector<std::string>::iterator it = request.extra_headers.begin(); it != request.extra_headers.end(); ++it) { http_header = curl_slist_append(http_header, it->c_str()); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_header); if (!g_settings->getBool("curl_verify_cert")) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); } } CURLcode HTTPFetchOngoing::start(CURLM *multi_) { if (!curl) return CURLE_FAILED_INIT; if (!multi_) { // Easy interface (sync) return curl_easy_perform(curl); } // Multi interface (async) CURLMcode mres = curl_multi_add_handle(multi_, curl); if (mres != CURLM_OK) { errorstream << "curl_multi_add_handle" << " returned error code " << mres << std::endl; return CURLE_FAILED_INIT; } multi = multi_; // store for curl_multi_remove_handle return CURLE_OK; } const HTTPFetchResult * HTTPFetchOngoing::complete(CURLcode res) { result.succeeded = (res == CURLE_OK); result.timeout = (res == CURLE_OPERATION_TIMEDOUT); result.data = oss.str(); // Get HTTP/FTP response code result.response_code = 0; if (curl && (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &result.response_code) != CURLE_OK)) { // We failed to get a return code, make sure it is still 0 result.response_code = 0; } if (res != CURLE_OK) { errorstream << request.url << " not found (" << curl_easy_strerror(res) << ")" << " (response code " << result.response_code << ")" << std::endl; } return &result; } HTTPFetchOngoing::~HTTPFetchOngoing() { if (multi) { CURLMcode mres = curl_multi_remove_handle(multi, curl); if (mres != CURLM_OK) { errorstream << "curl_multi_remove_handle" << " returned error code " << mres << std::endl; } } // Set safe options for the reusable cURL handle curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, httpfetch_discardfunction); curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL); if (http_header) { curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); curl_slist_free_all(http_header); } if (post) { curl_easy_setopt(curl, CURLOPT_HTTPPOST, NULL); curl_formfree(post); } // Store the cURL handle for reuse pool->free(curl); } class CurlFetchThread : public Thread { protected: enum RequestType { RT_FETCH, RT_CLEAR, RT_WAKEUP, }; struct Request { RequestType type; HTTPFetchRequest fetch_request; Event *event; }; CURLM *m_multi; MutexedQueue<Request> m_requests; size_t m_parallel_limit; // Variables exclusively used within thread std::vector<HTTPFetchOngoing*> m_all_ongoing; std::list<HTTPFetchRequest> m_queued_fetches; public: CurlFetchThread(int parallel_limit) : Thread("CurlFetch") { if (parallel_limit >= 1) m_parallel_limit = parallel_limit; else m_parallel_limit = 1; } void requestFetch(const HTTPFetchRequest &fetch_request) { Request req; req.type = RT_FETCH; req.fetch_request = fetch_request; req.event = NULL; m_requests.push_back(req); } void requestClear(unsigned long caller, Event *event) { Request req; req.type = RT_CLEAR; req.fetch_request.caller = caller; req.event = event; m_requests.push_back(req); } void requestWakeUp() { Request req; req.type = RT_WAKEUP; req.event = NULL; m_requests.push_back(req); } protected: // Handle a request from some other thread // E.g. new fetch; clear fetches for one caller; wake up void processRequest(const Request &req) { if (req.type == RT_FETCH) { // New fetch, queue until there are less // than m_parallel_limit ongoing fetches m_queued_fetches.push_back(req.fetch_request); // see processQueued() for what happens next } else if (req.type == RT_CLEAR) { unsigned long caller = req.fetch_request.caller; // Abort all ongoing fetches for the caller for (std::vector<HTTPFetchOngoing*>::iterator it = m_all_ongoing.begin(); it != m_all_ongoing.end();) { if ((*it)->getRequest().caller == caller) { delete (*it); it = m_all_ongoing.erase(it); } else { ++it; } } // Also abort all queued fetches for the caller for (std::list<HTTPFetchRequest>::iterator it = m_queued_fetches.begin(); it != m_queued_fetches.end();) { if ((*it).caller == caller) it = m_queued_fetches.erase(it); else ++it; } } else if (req.type == RT_WAKEUP) { // Wakeup: Nothing to do, thread is awake at this point } if (req.event != NULL) req.event->signal(); } // Start new ongoing fetches if m_parallel_limit allows void processQueued(CurlHandlePool *pool) { while (m_all_ongoing.size() < m_parallel_limit && !m_queued_fetches.empty()) { HTTPFetchRequest request = m_queued_fetches.front(); m_queued_fetches.pop_front(); // Create ongoing fetch data and make a cURL handle // Set cURL options based on HTTPFetchRequest HTTPFetchOngoing *ongoing = new HTTPFetchOngoing(request, pool); // Initiate the connection (curl_multi_add_handle) CURLcode res = ongoing->start(m_multi); if (res == CURLE_OK) { m_all_ongoing.push_back(ongoing); } else { httpfetch_deliver_result(*ongoing->complete(res)); delete ongoing; } } } // Process CURLMsg (indicates completion of a fetch) void processCurlMessage(CURLMsg *msg) { // Determine which ongoing fetch the message pertains to size_t i = 0; bool found = false; for (i = 0; i < m_all_ongoing.size(); ++i) { if (m_all_ongoing[i]->getEasyHandle() == msg->easy_handle) { found = true; break; } } if (msg->msg == CURLMSG_DONE && found) { // m_all_ongoing[i] succeeded or failed. HTTPFetchOngoing *ongoing = m_all_ongoing[i]; httpfetch_deliver_result(*ongoing->complete(msg->data.result)); delete ongoing; m_all_ongoing.erase(m_all_ongoing.begin() + i); } } // Wait for a request from another thread, or timeout elapses void waitForRequest(long timeout) { if (m_queued_fetches.empty()) { try { Request req = m_requests.pop_front(timeout); processRequest(req); } catch (ItemNotFoundException &e) {} } } // Wait until some IO happens, or timeout elapses void waitForIO(long timeout) { fd_set read_fd_set; fd_set write_fd_set; fd_set exc_fd_set; int max_fd; long select_timeout = -1; struct timeval select_tv; CURLMcode mres; FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&exc_fd_set); mres = curl_multi_fdset(m_multi, &read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); if (mres != CURLM_OK) { errorstream<<"curl_multi_fdset" <<" returned error code "<<mres <<std::endl; select_timeout = 0; } mres = curl_multi_timeout(m_multi, &select_timeout); if (mres != CURLM_OK) { errorstream<<"curl_multi_timeout" <<" returned error code "<<mres <<std::endl; select_timeout = 0; } // Limit timeout so new requests get through if (select_timeout < 0 || select_timeout > timeout) select_timeout = timeout; if (select_timeout > 0) { // in Winsock it is forbidden to pass three empty // fd_sets to select(), so in that case use sleep_ms if (max_fd != -1) { select_tv.tv_sec = select_timeout / 1000; select_tv.tv_usec = (select_timeout % 1000) * 1000; int retval = select(max_fd + 1, &read_fd_set, &write_fd_set, &exc_fd_set, &select_tv); if (retval == -1) { #ifdef _WIN32 errorstream<<"select returned error code " <<WSAGetLastError()<<std::endl; #else errorstream<<"select returned error code " <<errno<<std::endl; #endif } } else { sleep_ms(select_timeout); } } } void *run() { DSTACK(FUNCTION_NAME); CurlHandlePool pool; m_multi = curl_multi_init(); if (m_multi == NULL) { errorstream<<"curl_multi_init returned NULL\n"; return NULL; } FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty"); while (!stopRequested()) { BEGIN_DEBUG_EXCEPTION_HANDLER /* Handle new async requests */ while (!m_requests.empty()) { Request req = m_requests.pop_frontNoEx(); processRequest(req); } processQueued(&pool); /* Handle ongoing async requests */ int still_ongoing = 0; while (curl_multi_perform(m_multi, &still_ongoing) == CURLM_CALL_MULTI_PERFORM) /* noop */; /* Handle completed async requests */ if (still_ongoing < (int) m_all_ongoing.size()) { CURLMsg *msg; int msgs_in_queue; msg = curl_multi_info_read(m_multi, &msgs_in_queue); while (msg != NULL) { processCurlMessage(msg); msg = curl_multi_info_read(m_multi, &msgs_in_queue); } } /* If there are ongoing requests, wait for data (with a timeout of 100ms so that new requests can be processed). If no ongoing requests, wait for a new request. (Possibly an empty request that signals that the thread should be stopped.) */ if (m_all_ongoing.empty()) waitForRequest(100000000); else waitForIO(100); END_DEBUG_EXCEPTION_HANDLER } // Call curl_multi_remove_handle and cleanup easy handles for (size_t i = 0; i < m_all_ongoing.size(); ++i) { delete m_all_ongoing[i]; } m_all_ongoing.clear(); m_queued_fetches.clear(); CURLMcode mres = curl_multi_cleanup(m_multi); if (mres != CURLM_OK) { errorstream<<"curl_multi_cleanup" <<" returned error code "<<mres <<std::endl; } return NULL; } }; CurlFetchThread *g_httpfetch_thread = NULL; void httpfetch_init(int parallel_limit) { verbosestream<<"httpfetch_init: parallel_limit="<<parallel_limit <<std::endl; CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);