examples/xep0047.lua
changeset 42 18d801679feb
parent 38 1f141d9a081a
equal deleted inserted replaced
41:9e39fd8a20df 42:18d801679feb
     1 
     1 
     2 receiving_files = {}
     2 receiving_files = {}
     3 ibb_block_size  = 4096
     3 ibb_block_size  = 4096
     4 current_sid_number = 0
     4 local ibb_sid = 0
     5 
       
     6 -- FIXME: read from /dev/urandom?
       
     7 function gen_unique_sid ()
       
     8 	current_sid_number = current_sid_number + 1
       
     9 	return 'mc-' .. tostring ( current_sid_number )
       
    10 end
       
    11 
     5 
    12 ibb_incoming_iq_handler = lm.message_handler.new ( 
     6 ibb_incoming_iq_handler = lm.message_handler.new ( 
    13 	function ( conn, mess )
     7 	function ( conn, mess )
    14 		local id   = mess:attribute ( 'id' )
     8 		local id   = mess:attribute ( 'id' )
    15 		local from = mess:attribute ( 'from' )
     9 		local from = mess:attribute ( 'from' )
    98 		end
    92 		end
    99 
    93 
   100 		return false
    94 		return false
   101 	end )
    95 	end )
   102 
    96 
   103 function ibb_send_file ( conn, to, name )
    97 function ibb_send_file ( conn, to, name, id )
   104 	if not to then
    98 	if not to then
   105 		to = main.full_jid ()
    99 		to = main.full_jid ()
   106 	elseif not to:match ( "/" ) then
   100 	elseif not to:match ( "/" ) then
   107 		to = main.full_jid ( to )
   101 		to = main.full_jid ( to )
   108 	end
   102 	end
   109 	local sid = gen_unique_sid ()
   103 	local sid = id
       
   104 	if not sid then -- XXX: move out of here?
       
   105 		ibb_sid = ibb_sid + 1
       
   106 		sid = 'ibb_' .. ibb_sid
       
   107 	end
   110 	conn:send (
   108 	conn:send (
   111 		lm.message.create { to = to, mtype = 'iq-set',
   109 		lm.message.create { to = to, mtype = 'iq-set',
   112 			open = { sid = sid, ['block-size'] = ibb_block_size, xmlns = 'http://jabber.org/protocol/ibb' }
   110 			open = { sid = sid, ['block-size'] = ibb_block_size, xmlns = 'http://jabber.org/protocol/ibb' }
   113 		},
   111 		},
   114 		function ( conn, message )
   112 		function ( conn, message )
   115 			if message:child ( 'error' ) then
   113 			if message:child ( 'error' ) then
   116 				main.print_info ( to, "Stream request refused: " .. message:child( 'error' ):children():name () )
   114 				main.print_info ( to, "Stream request refused: " .. message:child( 'error' ):children():name () )
   117 			else
   115 			else
   118 				main.print_info ( to, "Stream accepted, starting sequence" )
   116 				main.print_info ( to, "Stream accepted, starting sequence" )
   119 				local buffer = ''
   117 				local buffer = ''
   120 				main.bgread ( string.format ( 'base64 -w 0 %q', name ),
   118 				main.bgread ( string.format ( 'base64 -w 0 %q', name ), -- FIXME: stream reader function? XXX: then we need in-place base64 encoder.
   121 					function ( data )
   119 					function ( data )
   122 						if data then
   120 						if data then
   123 							buffer = buffer .. data
   121 							buffer = buffer .. data
   124 							return true
   122 							return true
   125 						else
   123 						else
   126 							local seq = 0
   124 							local seq = 0
   127 							local msgbuf = buffer:sub ( 1, ibb_block_size )
   125 							local msgbuf = buffer:sub ( 1, ibb_block_size )
   128 							buffer = buffer:sub ( ibb_block_size + 1 )
   126 							buffer = buffer:sub ( ibb_block_size + 1 )
   129 							local function handler ( conn, message )
   127 							local function handler ( conn, mess )
   130 								if message:child ( 'error' ) then
   128 								local mtype, smtype = mess:type ()
       
   129 								if smtype == 'error' then
   131 									main.print_info ( to, "Stream error, transfer ceased at seq = " .. seq .. ": " .. message:child( 'error' ):children():name () )
   130 									main.print_info ( to, "Stream error, transfer ceased at seq = " .. seq .. ": " .. message:child( 'error' ):children():name () )
   132 								else
   131 								elseif smtype == 'result' then
   133 									main.print_info ( to, " - acquired seq = " .. seq )
   132 									main.print_info ( to, " - acquired seq = " .. seq )
   134 									seq = seq + 1
   133 									seq = seq + 1
   135 									if buffer:len () == 0 then
   134 									if buffer:len () == 0 then
   136 										conn:send (
   135 										conn:send (
   137 											lm.message.create { to = to, mtype = 'iq-set',
   136 											lm.message.create { to = to, mtype = 'iq-set',
   138 												close = { sid = sid, xmlns = 'http://jabber.org/protocol/ibb' }
   137 												close = { sid = sid, xmlns = 'http://jabber.org/protocol/ibb' }
   139 											},
   138 											},
   140 											function ( conn, message )
   139 											function ( conn, mess )
   141 												if message:child ( 'error' ) then
   140 												local mtype, smtype = mess:type ()
   142 													main.print_info ( to, "Error at closing stream: " .. message:child( 'error' ):children():name () )
   141 												if smtype == 'error' then
       
   142 													main.print_info ( to, "Error at closing stream: " .. mess:child( 'error' ):children():name () )
       
   143 												elseif smtype == 'result' then
       
   144 													main.print_info ( to, "File successfully transferred" )
   143 												else
   145 												else
   144 													main.print_info ( to, "File successfully transferred" )
   146 													print ( 'Weird response for close of ibb stream: ' .. mess:xml () )
       
   147 													return false
   145 												end
   148 												end
   146 												return true
   149 												return true
   147 											end )
   150 											end )
   148 									else
   151 									else
   149 										local msgbuf = buffer:sub ( 1, ibb_block_size )
   152 										local msgbuf = buffer:sub ( 1, ibb_block_size )
   154 													msgbuf
   157 													msgbuf
   155 												}
   158 												}
   156 											},
   159 											},
   157 											handler )
   160 											handler )
   158 									end
   161 									end
       
   162 								else
       
   163 									print ( 'Weird response for ibb block: ' .. mess:xml () )
       
   164 									return false
   159 								end
   165 								end
   160 								return true
   166 								return true
   161 							end
   167 							end
   162 							conn:send (
   168 							conn:send (
   163 								lm.message.create { to = to, mtype = 'iq-set',
   169 								lm.message.create { to = to, mtype = 'iq-set',