+++ /dev/null
-require "socket"
-
-=begin
-
- BuildComm.rb
-
-Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-
-Contact:
-Taejun Ha <taejun.ha@samsung.com>
-Jiil Hyoun <jiil.hyoun@samsung.com>
-Donghyuk Yang <donghyuk.yang@samsung.com>
-DongHee Yang <donghee.yang@samsung.com>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-Contributors:
-- S-Core Co., Ltd
-=end
-
-$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
-require "log"
-require 'timeout'
-require "fileTransfer"
-require "net/ftp"
-require 'thread'
-
-ATTEMPTS = ["first", "second", "third"]
-
-class BuildCommServer
- VERSION = "1.5.0"
-
- private_class_method :new
-
- def initialize(port, log, ftp_url, cache_dir)
- @port = port
- @log = log
- @ftp_url = ftp_url
- @cache_dir = cache_dir
- @tcp_server = TCPServer.open( port )
- @download_cache_mutex = Mutex.new
- end
-
- def self.create(port, log, ftp_url=nil, cache_dir=nil)
- # checking port is available
- if port_open? port then
- raise "Port \"#{@port}\" is already in use."
- end
-
- if log.nil? then
- log = DummyLog.new
- end
-
- # create cache dir if not nil
- if not cache_dir.nil? and not File.exist? cache_dir then
- FileUtils.mkdir_p cache_dir
- end
-
- return new(port, log, ftp_url, cache_dir)
- end
-
-
- # wait for connection and handle request
- def wait_for_connection(quit_loop)
- while( not quit_loop )
- req = @tcp_server.accept
-
- begin
- yield req if block_given?
- rescue
- @log.error $!
- @log.error "Caught a connection exception"
- req.close
- end
- end
- end
-
-
- # terminate
- def terminate
- @tcp_server.close()
- end
-
-
- # send_begin
- def self.send_begin( req )
- send( req, "=BEGIN,#{VERSION}")
- end
-
-
- def self.send_end( req )
- send( req, "=END")
- end
-
-
- def self.send_chk( req )
- send( req, "=CHK" )
- end
-
-
- def self.send( req, line )
- begin
- if not req.nil? then
- req.puts line
- end
- rescue
- raise "Connection is closed"
- end
- end
-
-
- def send_file(req, src_file)
- # 1. send "READY"
- # 2. If "FTP,ip,username,passwd" is received,
- # Upload the src file using server's ftp_url.
- # if then ftp_url is nil, use the url on "FTP" message instead
- # After uploading, send "UPLOADED,ftp_filepath"
- # 3. If "SUCC" is received, remove the file on FTP server
-
- begin
- if not File.exist? src_file then
- @log.error "\"#{src_file}\" file does not exist"
- req.puts "ERROR"
- return false
- end
-
- req.puts "READY"
- @log.info "Ready to upload file"
- while l = req.gets()
- tok = l.split(",").map { |x| x.strip }
- cmd = tok[0].strip
- if cmd == "FTP" then
- if tok.count < 5 then
- @log.error "Server received wrong REQ : #{l.strip}"
- req.puts "ERROR"
- return false
- end
-
- # get ftp connection info
- if @ftp_url.nil? then
- ip = tok[1].strip
- port = tok[2].strip
- username = tok[3].strip
- passwd = tok[4].strip
- @log.info "Server received ftp server infomation from client : [#{ip}, #{port}]"
- else
- url_contents = Utils.parse_ftpserver_url(@ftp_url)
- ip = url_contents[0]
- port = url_contents[1]
- username = url_contents[2]
- passwd = url_contents[3]
- end
-
- # upload to ftp server
- ftp_filepath = nil
- @trans = FileTransfer.new(ip, port, username, passwd, @log)
- for attempt in ATTEMPTS
- ftp_filepath = @trans.putfile( src_file )
- if !ftp_filepath.nil? then break;
- else @log.info "Server is the #{attempt} upload attempt fails" end
- end
- if ftp_filepath.nil? then
- req.puts "ERROR"
- return false
- else
- @log.info "Server is the #{attempt} successful attempt to upload file: [#{File.basename(src_file)}]"
- end
- req.puts "UPLOADED,#{ftp_filepath}"
- elsif cmd == "SUCC" then
- @log.info "Client downloaded file successfully"
- @trans.cleandir( ftp_filepath )
- @log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}"
- break
- elsif cmd == "ERROR" then
- @log.error "Client failed to download file"
- return false
- end
- end
- rescue => e
- puts "[BuildCommServer] Exception"
- @log.error e.message
- @log.error e.backtrace.inspect
- return false
- end
-
- return true
- end
-
-
- # NOTE. dst_file can be directory
- def receive_file(req, dst_file)
- # 1. send "READY"
- # 2. If "UPLOADED,ip,port,file_path,username,passwd" is received,
- # Download the file using my ftp_url.
- # If ftp_url is nil, use the url on "UPLOADED" messge instead
- # After downloading it, send "SUCC"
-
- begin
- req.puts "READY"
- while l = req.gets()
- tok = l.split(",").map { |x| x.strip }
- cmd = tok[0].strip
- if cmd == "CHECK_CACHE" then
- file_name = tok[1]
- file_size = tok[2].to_i
- checksum = tok[3]
-
- # check download cache
- if File.exist? dst_file and File.directory? dst_file then
- target_file = File.join(dst_file,file_name)
- else
- target_file = dst_file
- end
- if not @cache_dir.nil? and
- check_download_cache( target_file, file_size, checksum ) then
-
- @log.info "Download cache hit! Copied from cache.: #{file_name}"
- req.puts "CACHED"
- break
- else
- @log.info "Cached file not found!#{file_name}"
- req.puts "NOT_CACHED"
- end
- elsif cmd == "UPLOADED" then
- @log.info "Client uploaded file to ftp server successful"
- if tok.count < 6 then
- @log.error "Server received wrong REQ : #{l.strip}"
- req.puts "ERROR"
- return false
- end
- filepath = tok[3].strip
-
- # get ftp connection info
- if @ftp_url.nil? then
- ip = tok[1].strip
- port = tok[2].strip
- username = tok[4].strip
- passwd = tok[5].strip
- @log.info "Client sent ftp server infomations [#{ip}, #{port}]"
- else
- url_contents = Utils.parse_ftpserver_url(@ftp_url)
- ip = url_contents[0]
- port = url_contents[1]
- username = url_contents[2]
- passwd = url_contents[3]
- end
-
- # download from ftp server
- dst_filepath = nil
- @trans = FileTransfer.new(ip, port, username, passwd, @log)
- for attempt in ATTEMPTS
- dst_filepath = @trans.getfile( filepath, dst_file )
- if not dst_filepath.nil? then break
- else
- @log.warn "Server is the #{attempt} download attempt fails"
- end
- end
- if dst_filepath.nil? then
- req.puts "ERROR"
- return false
- else @log.info " Server is the #{attempt} successful attempt to download" end
-
- # add to cache
- if not @cache_dir.nil? then
- if File.exist? dst_file and File.directory? dst_file then
- target_file = File.join(dst_file,File.basename(dst_filepath))
- else
- target_file = dst_file
- end
- add_download_cache(target_file)
- end
-
- req.puts "SUCC"
- break
- elsif cmd == "ERROR" then
- @log.error "Client failed to upload the file"
- return false
- else
- @log.warn "Unhandled message: #{l}"
- end
- end
- rescue => e
- puts "[BuildCommServer] Exception"
- @log.error e.message
- @log.error e.backtrace.inspect
- return false
- end
-
- return true
- end
-
-
- def self.disconnect( req )
- begin
- req.close
- rescue
- end
- end
-
- def self.port_open?( port )
- Timeout::timeout(1) do
- begin
- TCPSocket.new("127.0.0.1",port).close
- true
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
- false
- end
- end
- rescue Timeout::Error
- false
- end
-
-
- private
- def check_download_cache(dst_file, file_size, checksum )
- file_name = File.basename(dst_file)
- cache_file = "#{@cache_dir}/#{file_name}"
-
- @download_cache_mutex.synchronize {
- found = false
- # check file exist
- if File.exist? cache_file and
- File.size(cache_file) == file_size and
- Utils.checksum(cache_file) == checksum then
-
- # if hit , touch and copy
- FileUtils.touch cache_file
- FileUtils.copy_file(cache_file, dst_file)
-
- found = true
- end
-
- # refresh cache dir
- curr_time = Time.now
- Dir.entries(@cache_dir).each { |fname|
- if fname == "." or fname == ".." then next end
- file_path = "#{@cache_dir}/#{fname}"
- if File.mtime(file_path) + 3600 < curr_time then
- FileUtils.rm_rf file_path
- end
- }
-
- return found
- }
- end
-
-
- private
- def add_download_cache(dst_file)
- file_name = File.basename(dst_file)
- cache_file = "#{@cache_dir}/#{file_name}"
- @download_cache_mutex.synchronize {
- # copy & touch
- FileUtils.copy_file(dst_file, cache_file)
- FileUtils.touch cache_file
- }
- end
-end
-
-
-class BuildCommClient
- VERSION = "1.5.0"
-
- private_class_method :new
-
- def initialize(socket, log)
- @log = log
- @socket = socket
- end
-
-
- # create
- # if sec 0 or nil then not set timeout. it's timeout spec
- def self.create(ip, port, log = nil, sec = 5)
- # open socket
- socket = nil
- begin
- timeout(sec) do
- socket = TCPSocket.open( ip, port )
- end
- rescue Timeout::Error
- return nil
- rescue
- # unknown exception
- return nil
- end
-
- # refused
- if socket.nil? then
- return nil
- end
-
- if log.nil? then
- log = DummyLog.new
- end
-
- return new(socket, log)
- end
-
-
- def send( msg )
- if @socket.nil? then return false end
-
- @socket.puts( msg )
- return true
- end
-
-
- def print_stream
-
- begin
- l = @socket.gets()
-
- if l.nil? then
- puts "Connection refused"
- return false
- end
-
- # check protocol
- if not protocol_matched? l.strip then
- puts "Comm. Protocol version is mismatched! #{VERSION}"
- return false
- end
-
-
- # get contents
- while line = @socket.gets()
- if line.strip == "=END" then break end
- if line.strip == "=CHK" then next end
- # print
- puts line.strip
- end
- rescue
- puts "Connection closed"
- return false
- end
-
- return true
- end
-
-
- # handle
- def read_lines
-
- begin
- # get first line
- l = nil
- timeout(5) do
- l = @socket.gets()
- end
-
- if l.nil? then
- return false
- end
-
- # check protocol
- if not protocol_matched? l.strip then
- return false
- end
-
- # get contents
- while line = @socket.gets()
- if line.strip == "=END" then break end
- if line.strip == "=CHK" then next end
-
- # print
- yield line.strip if block_given?
- end
- rescue Timeout::Error
- puts "WARN: Connection timed out"
- return false
- rescue => e
- puts e.message
- return false
- end
-
- return true
- end
-
-
- # return result
- def receive_data
- result = []
-
- begin
- l = @socket.gets()
-
- if l.nil? then
- puts "Connection refused"
- return nil
- end
-
- # check protocol
- if not protocol_matched? l.strip then
- puts "Comm. Protocol version is mismatched! #{VERSION}"
- return nil
- end
-
-
- # get contents
- while line = @socket.gets()
- if line.strip == "=END" then break end
- if line.strip == "=CHK" then next end
- # print
- result.push line.strip
- end
- rescue
- puts "Connection closed"
- return nil
- end
-
- return result
- end
-
-
- def send_file(ip, port, username, passwd, src_file)
- begin
- l = @socket.gets()
- if l.nil? then
- @log.error "[BuildCommClient] Connection refused"
- return false
- end
-
- # check protocol
- if not protocol_matched? l.strip then
- @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}"
- return false
- end
-
- # 1. If "READY" is received, upload src file to FTP server
- # After uploading it, send "UPLOADED,ip,file_path,username,passwd"
- # 2. If "SUCC" is received, remove the file on FTP server
- while line = @socket.gets()
- if line.strip == "READY" then
- @log.info "Server is ready to receive file"
- file_name = File.basename(src_file)
- file_size = File.size(src_file)
- checksum = Utils.checksum(src_file)
- send "CHECK_CACHE,#{file_name},#{file_size},#{checksum}"
- elsif line.strip == "CACHED" then
- @log.info "Server already has cached file"
- elsif line.strip == "NOT_CACHED" then
- @log.info "Server doest not have cached file"
-
- ftp_filepath = nil
- @trans = FileTransfer.new(ip, port, username, passwd, @log)
- for attempt in ATTEMPTS
- ftp_filepath = @trans.putfile( src_file )
- if !ftp_filepath.nil? then break;
- else @log.info "Client is the #{attempt} upload attempt fails" end
- end
- if ftp_filepath.nil? then
- send "ERROR"
- return false
- else @log.info "Client is the #{attempt} successful attempt to upload file" end
- send "UPLOADED,#{ip},#{port},#{ftp_filepath},#{username},#{passwd}"
- elsif line.strip == "SUCC" then
- @log.info "Server downloaded file sucessfully"
- @trans.cleandir( ftp_filepath )
- @log.info "Client cleaned temporary dir on ftp server: #{ftp_filepath}"
- elsif line.strip == "ERROR" then
- @log.error "Server failed to download the file. Please check server log"
- return false
- elsif line.strip == "=END" then
- break
- end
- end
- rescue => e
- puts "[BuildCommClient] Exception"
- @log.error e.message
- @log.error e.backtrace.inspect
- return false
- end
-
- return true
- end
-
-
- # return file
- def receive_file(ip, port, username, passwd, dst_file)
- begin
- l = @socket.gets()
-
- if l.nil? then
- @log.error "[BuildCommClient] Connection refused"
- return false
- end
-
- # check protocol
- if not protocol_matched? l.strip then
- @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}"
- return false
- end
-
- # 1. If "READY" is received, send "FTP,ip,port,username,passwd"
- # 2. if "UPLOADED,ftp_file_path" is received,
- # Download the file
- # Send "SUCC"
- # 3. If "SUCC" is received, remove the file on FTP server
- while line = @socket.gets()
- cmd = line.split(",")[0].strip
- #@log.info "[BuildCommClient] Received \"#{cmd}\" message from BuildCommServer"
- if cmd == "READY" then
- send "FTP,#{ip},#{port},#{username},#{passwd}"
- @log.info "Client sent ftp server infomation to server : [#{ip}, #{port}]"
- elsif cmd == "UPLOADED" then
- tok = line.split(",")
- if tok.length < 2 then
- @log.error "Client received wrong REQ : #{line.strip}"
- return false
- end
- ftp_filepath = tok[1].strip
- @log.info "Server uploaded file sucessfully"
- dst_filepath = nil
- @trans = FileTransfer.new(ip, port, username, passwd, @log)
- for attempt in ATTEMPTS
- dst_filepath = @trans.getfile( ftp_filepath, dst_file )
- if not dst_filepath.nil? then break
- else
- @log.warn "Client is the #{attempt} download attempt fails"
- end
- end
- if dst_filepath.nil? then
- send "ERROR"
- return false
- else @log.info "Client is the #{attempt} successful attempt to download" end
- send "SUCC"
- elsif cmd == "ERROR" then
- @log.error "Server failed to upload file. Check server log"
- return false
- elsif cmd == "=END" then
- break
- end
- end
- rescue => e
- puts "[BuildCommServer] Exception"
- @log.error e.message
- @log.error e.backtrace.inspect
- return false
- end
-
- return true
- end
-
-
- def terminate
- @socket.close
- end
-
-
- private
-
-
- # check protocol
- def protocol_matched?(l)
-
- version = ( l.split(",")[1].nil? ? "1.0.0" : l.split(",")[1] )
- if not l.start_with? "=BEGIN" or
- version.nil? or version != VERSION then
- return false
- else
- return true
- end
- end
-end
--- /dev/null
+require "socket"
+
+=begin
+
+ BuildComm.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Contributors:
+- S-Core Co., Ltd
+=end
+
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require "log"
+require 'timeout'
+require "fileTransfer"
+require "net/ftp"
+require 'thread'
+
+ATTEMPTS = ["first", "second", "third"]
+
+class BuildCommServer
+ VERSION = "1.5.0"
+
+ private_class_method :new
+
+ def initialize(port, log, ftp_url, cache_dir)
+ @port = port
+ @log = log
+ @ftp_url = ftp_url
+ @cache_dir = cache_dir
+ @tcp_server = TCPServer.open( port )
+ @download_cache_mutex = Mutex.new
+ end
+
+ def self.create(port, log, ftp_url=nil, cache_dir=nil)
+ # checking port is available
+ if port_open? port then
+ raise "Port \"#{@port}\" is already in use."
+ end
+
+ if log.nil? then
+ log = DummyLog.new
+ end
+
+ # create cache dir if not nil
+ if not cache_dir.nil? and not File.exist? cache_dir then
+ FileUtils.mkdir_p cache_dir
+ end
+
+ return new(port, log, ftp_url, cache_dir)
+ end
+
+
+ # wait for connection and handle request
+ def wait_for_connection(quit_loop)
+ while( not quit_loop )
+ req = @tcp_server.accept
+
+ begin
+ yield req if block_given?
+ rescue
+ @log.error $!
+ @log.error "Caught a connection exception"
+ req.close
+ end
+ end
+ end
+
+
+ # terminate
+ def terminate
+ @tcp_server.close()
+ end
+
+
+ # send_begin
+ def self.send_begin( req )
+ send( req, "=BEGIN,#{VERSION}")
+ end
+
+
+ def self.send_end( req )
+ send( req, "=END")
+ end
+
+
+ def self.send_chk( req )
+ send( req, "=CHK" )
+ end
+
+
+ def self.send( req, line )
+ begin
+ if not req.nil? then
+ req.puts line
+ end
+ rescue
+ raise "Connection is closed"
+ end
+ end
+
+
+ def send_file(req, src_file)
+ begin
+ if not File.exist? src_file then
+ @log.error "\"#{src_file}\" file does not exist"
+ req.puts "ERROR"
+ return false
+ end
+
+ req.puts "READY"
+ @log.info "Ready to upload file"
+
+ # receive file from client
+ if not @ftp_url.nil? then
+ url_contents = Utils.parse_ftpserver_url(@ftp_url)
+ ip = url_contents[0]
+ port = url_contents[1]
+ username = url_contents[2]
+ passwd = url_contents[3]
+ @trans = FileTransfer.new(@log,ip,port,username,passwd)
+ else
+ @trans = FileTransfer.new(@log)
+ end
+
+ if not @trans.send_file( src_file, req, false ) then
+ return false
+ end
+
+ rescue => e
+ puts "[BuildCommServer] Exception"
+ @log.error e.message
+ @log.error e.backtrace.inspect
+ return false
+ end
+
+ return true
+ end
+
+
+ # NOTE. dst_file can be directory
+ def receive_file(req, dst_file)
+ # 1. send "READY"
+ # 2. If "UPLOADED,ip,port,file_path,username,passwd" is received,
+ # Download the file using my ftp_url.
+ # If ftp_url is nil, use the url on "UPLOADED" messge instead
+ # After downloading it, send "SUCC"
+
+ begin
+ req.puts "READY"
+ while l = req.gets()
+ tok = l.split(",").map { |x| x.strip }
+ cmd = tok[0].strip
+ if cmd == "CHECK_CACHE" then
+ file_name = tok[1]
+ file_size = tok[2].to_i
+ checksum = tok[3]
+
+ # check download cache
+ if File.exist? dst_file and File.directory? dst_file then
+ target_file = File.join(dst_file,file_name)
+ else
+ target_file = dst_file
+ end
+ if not @cache_dir.nil? and
+ check_download_cache( target_file, file_size, checksum ) then
+
+ @log.info "Download cache hit! Copied from cache.: #{file_name}"
+ req.puts "CACHED"
+ else
+ @log.info "Cached file not found!#{file_name}"
+ req.puts "NOT_CACHED"
+
+ # receive file from client
+ if not @ftp_url.nil? then
+ url_contents = Utils.parse_ftpserver_url(@ftp_url)
+ ip = url_contents[0]
+ port = url_contents[1]
+ username = url_contents[2]
+ passwd = url_contents[3]
+ @trans = FileTransfer.new(@log, ip, port, username, passwd)
+ else
+ @trans = FileTransfer.new(@log)
+ end
+
+ if not @trans.receive_file( dst_file, req, false ) then
+ return false
+ end
+
+ # add to cache
+ if not @cache_dir.nil? then
+ if File.exist? dst_file and File.directory? dst_file then
+ target_file = File.join(dst_file,File.basename(dst_filepath))
+ else
+ target_file = dst_file
+ end
+ add_download_cache(target_file)
+ end
+ end
+ break
+
+ else
+ @log.warn "Unhandled message: #{l}"
+ end
+ end
+ rescue => e
+ puts "[BuildCommServer] Exception"
+ @log.error e.message
+ @log.error e.backtrace.inspect
+ return false
+ end
+
+ return true
+ end
+
+
+ def self.disconnect( req )
+ begin
+ req.close
+ rescue
+ end
+ end
+
+ def self.port_open?( port )
+ Timeout::timeout(1) do
+ begin
+ TCPSocket.new("127.0.0.1",port).close
+ true
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
+ false
+ end
+ end
+ rescue Timeout::Error
+ false
+ end
+
+
+ private
+ def check_download_cache(dst_file, file_size, checksum )
+ file_name = File.basename(dst_file)
+ cache_file = "#{@cache_dir}/#{file_name}"
+
+ @download_cache_mutex.synchronize {
+ found = false
+ # check file exist
+ if File.exist? cache_file and
+ File.size(cache_file) == file_size and
+ Utils.checksum(cache_file) == checksum then
+
+ # if hit , touch and copy
+ FileUtils.touch cache_file
+ FileUtils.copy_file(cache_file, dst_file)
+
+ found = true
+ end
+
+ # refresh cache dir
+ curr_time = Time.now
+ Dir.entries(@cache_dir).each { |fname|
+ if fname == "." or fname == ".." then next end
+ file_path = "#{@cache_dir}/#{fname}"
+ if File.mtime(file_path) + 3600 < curr_time then
+ FileUtils.rm_rf file_path
+ end
+ }
+
+ return found
+ }
+ end
+
+
+ private
+ def add_download_cache(dst_file)
+ file_name = File.basename(dst_file)
+ cache_file = "#{@cache_dir}/#{file_name}"
+ @download_cache_mutex.synchronize {
+ # copy & touch
+ FileUtils.copy_file(dst_file, cache_file)
+ FileUtils.touch cache_file
+ }
+ end
+end
+
+
+class BuildCommClient
+ VERSION = "1.5.0"
+
+ private_class_method :new
+
+ def initialize(socket, log)
+ @log = log
+ @socket = socket
+ end
+
+
+ # create
+ # if sec 0 or nil then not set timeout. it's timeout spec
+ def self.create(ip, port, log = nil, sec = 5)
+ # open socket
+ socket = nil
+ begin
+ timeout(sec) do
+ socket = TCPSocket.open( ip, port )
+ end
+ rescue Timeout::Error
+ return nil
+ rescue
+ # unknown exception
+ return nil
+ end
+
+ # refused
+ if socket.nil? then
+ return nil
+ end
+
+ if log.nil? then
+ log = DummyLog.new
+ end
+
+ return new(socket, log)
+ end
+
+
+ def send( msg )
+ if @socket.nil? then return false end
+
+ @socket.puts( msg )
+ return true
+ end
+
+
+ def print_stream
+
+ begin
+ l = @socket.gets()
+
+ if l.nil? then
+ puts "Connection refused"
+ return false
+ end
+
+ # check protocol
+ if not protocol_matched? l.strip then
+ puts "Comm. Protocol version is mismatched! #{VERSION}"
+ return false
+ end
+
+
+ # get contents
+ while line = @socket.gets()
+ if line.strip == "=END" then break end
+ if line.strip == "=CHK" then next end
+ # print
+ puts line.strip
+ end
+ rescue
+ puts "Connection closed"
+ return false
+ end
+
+ return true
+ end
+
+
+ # handle
+ def read_lines
+
+ begin
+ # get first line
+ l = nil
+ timeout(5) do
+ l = @socket.gets()
+ end
+
+ if l.nil? then
+ return false
+ end
+
+ # check protocol
+ if not protocol_matched? l.strip then
+ return false
+ end
+
+ # get contents
+ while line = @socket.gets()
+ if line.strip == "=END" then break end
+ if line.strip == "=CHK" then next end
+
+ # print
+ yield line.strip if block_given?
+ end
+ rescue Timeout::Error
+ puts "WARN: Connection timed out"
+ return false
+ rescue => e
+ puts e.message
+ return false
+ end
+
+ return true
+ end
+
+
+ # return result
+ def receive_data
+ result = []
+
+ begin
+ l = @socket.gets()
+
+ if l.nil? then
+ puts "Connection refused"
+ return nil
+ end
+
+ # check protocol
+ if not protocol_matched? l.strip then
+ puts "Comm. Protocol version is mismatched! #{VERSION}"
+ return nil
+ end
+
+
+ # get contents
+ while line = @socket.gets()
+ if line.strip == "=END" then break end
+ if line.strip == "=CHK" then next end
+ # print
+ result.push line.strip
+ end
+ rescue
+ puts "Connection closed"
+ return nil
+ end
+
+ return result
+ end
+
+
+ def send_file(ip, port, username, passwd, src_file)
+ begin
+ l = @socket.gets()
+ if l.nil? then
+ @log.error "[BuildCommClient] Connection refused"
+ return false
+ end
+
+ # check protocol
+ if not protocol_matched? l.strip then
+ @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}"
+ return false
+ end
+
+ while line = @socket.gets()
+ if line.strip == "READY" then
+ @log.info "Server is ready to receive file"
+ file_name = File.basename(src_file)
+ file_size = File.size(src_file)
+ checksum = Utils.checksum(src_file)
+ send "CHECK_CACHE,#{file_name},#{file_size},#{checksum}"
+
+ elsif line.strip == "CACHED" then
+ @log.info "Server already has cached file"
+ break
+
+ elsif line.strip == "NOT_CACHED" then
+ @log.info "Server doest not have cached file"
+
+ # send file to server
+ @trans = FileTransfer.new(@log, ip, port, username, passwd)
+ if not @trans.send_file( src_file, @socket, true ) then
+ return false
+ end
+ break
+
+ elsif line.strip == "=END" then
+ break
+ end
+ end
+ rescue => e
+ puts "[BuildCommClient] Exception"
+ @log.error e.message
+ @log.error e.backtrace.inspect
+ return false
+ end
+
+ return true
+ end
+
+
+ # return file
+ def receive_file(ip, port, username, passwd, dst_file)
+ begin
+ l = @socket.gets()
+
+ if l.nil? then
+ @log.error "[BuildCommClient] Connection refused"
+ return false
+ end
+
+ # check protocol
+ if not protocol_matched? l.strip then
+ @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}"
+ return false
+ end
+
+ while line = @socket.gets()
+ cmd = line.split(",")[0].strip
+ if cmd == "READY" then
+ @trans = FileTransfer.new(@log, ip, port, username, passwd)
+ if not @trans.receive_file( dst_file, @socket, true ) then
+ return false
+ end
+ break
+ elsif cmd == "=END" then
+ break
+ end
+ end
+ rescue => e
+ puts "[BuildCommServer] Exception"
+ @log.error e.message
+ @log.error e.backtrace.inspect
+ return false
+ end
+
+ return true
+ end
+
+
+ def terminate
+ @socket.close
+ end
+
+
+ private
+
+
+ # check protocol
+ def protocol_matched?(l)
+
+ version = ( l.split(",")[1].nil? ? "1.0.0" : l.split(",")[1] )
+ if not l.start_with? "=BEGIN" or
+ version.nil? or version != VERSION then
+ return false
+ else
+ return true
+ end
+ end
+end
require 'log'
class FileTransfer
- def initialize(ip, port, username, passwd, logger)
+ ATTEMPTS = ["first", "second", "third"]
+
+ def initialize(logger, ip=nil, port=nil, username=nil, passwd=nil )
@ip = ip
@port = port
@username = username
end
- def putfile( bpath )
+ def send_file( src_file, conn, is_client=true )
+
+ if is_client then
+ # check ftp info
+ if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+ @log.error "No FTP information!"
+ conn.puts "UPLOAD_FAIL"
+ return false
+ end
+ conn.puts "DOWNLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}"
+ end
+
+ ip = @ip; port = @port; username = @username; passwd = @passwd
+ while line = conn.gets()
+ tok = line.split(",") { |x| x.strip }
+ cmd = tok[0].strip
+ case cmd
+ when "UPLOAD_REQ"
+ if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+ ip = tok[1].strip
+ port = tok[2].strip
+ username = tok[3].strip
+ passwd = tok[4].strip
+ @log.info "Using FTP information from remote... [#{ip}, #{port}]"
+ end
+
+ # upload to ftp
+ ftp_filepath = nil
+ for attempt in ATTEMPTS
+ ftp_filepath = putfile( src_file, ip, port, username, passwd )
+ if !ftp_filepath.nil? then
+ break
+ else
+ @log.info "The #{attempt} uploading attempt failed!"
+ end
+ end
+
+ if ftp_filepath.nil? then
+ conn.puts "UPLOAD_FAIL"
+ return false
+ else
+ @log.info "Upload is succeeded at #{attempt}"
+ conn.puts "UPLOAD_OK,#{ftp_filepath}"
+ end
+
+ # wait for download result
+ when "DOWNLOAD_OK"
+ @log.info "Received download success message from remote site"
+ # clean
+ cleandir( ftp_filepath, ip, port, username, passwd)
+ @log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}"
+ return true
+
+ when "DOWNLOAD_FAIL"
+ @log.info "Received download fail message from remote site"
+ return false
+
+ else
+ @log.error "Unhandled message: #{line}"
+ return false
+ end
+ end
+ end
+
+
+ def receive_file( dst_file, conn, is_client=false )
+
+ if is_client then
+ # check ftp info
+ if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+ @log.error "No FTP information!"
+ conn.puts "DOWNLOAD_FAIL"
+ return false
+ end
+ conn.puts "UPLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}"
+ end
+
+ ip = @ip; port = @port; username = @username; passwd = @passwd
+ while line = conn.gets()
+ tok = line.split(",") { |x| x.strip }
+ cmd = tok[0].strip
+ case cmd
+ when "DOWNLOAD_REQ"
+ if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+ ip = tok[1].strip
+ port = tok[2].strip
+ username = tok[3].strip
+ passwd = tok[4].strip
+ @log.info "Using FTP information from remote... [#{ip}, #{port}]"
+ end
+
+ conn.puts "UPLOAD_REQ,#{ip},#{port},#{username},#{passwd}"
+ when "UPLOAD_OK"
+ @log.info "Received upload success message from remote site"
+ filepath = tok[1].strip
+ # download from ftp
+ dst_filepath = nil
+ for attempt in ATTEMPTS
+ dst_filepath = getfile( filepath, dst_file, ip, port, username, passwd )
+ if not dst_filepath.nil? then
+ break
+ else
+ @log.info "The #{attempt} downloading attempt failed!"
+ end
+ end
+ if dst_filepath.nil? then
+ conn.puts "DOWNLOAD_FAIL"
+ return false
+ else
+ @log.info " Server is the #{attempt} successful attempt to download"
+ conn.puts "DOWNLOAD_OK"
+ return true
+ end
+
+ when "UPLOAD_FAIL"
+ @log.info "Received upload fail message from remote site"
+ return false
+
+ else
+ @log.error "Unhandled message: #{line}"
+ return false
+ end
+ end
+ end
+
+
+ def putfile( bpath, ip, port, username, passwd )
filename = File.basename(bpath)
uniqdir = Utils.create_uniq_name
ftp_filepath = File.join(uniqdir, filename)
begin
ftp = Net::FTP.new
- if @port.nil? or @port == "" then
- ftp.connect(@ip)
+ if port.nil? or port == "" then
+ ftp.connect(ip)
else
- ftp.connect(@ip, @port)
+ ftp.connect(ip, port)
end
- @log.info "[FTP log] Connected FTP server (#{@ip}:#{@port})"
- ftp.login(@username, @passwd)
+ @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ ftp.login(username, passwd)
ftp.binary = true
ftp.passive = true
ftp.mkdir(uniqdir)
return ftp_filepath
end
- def getfile( bpath, target )
+ def getfile( bpath, target, ip, port, username, passwd )
dirname = File.dirname(bpath)
filename = File.basename(bpath)
begin
ftp = Net::FTP.new
- if @port.nil? or @port == "" then
- ftp.connect(@ip)
+ if port.nil? or port == "" then
+ ftp.connect(ip)
else
- ftp.connect(@ip, @port)
+ ftp.connect(ip, port)
end
- @log.info "[FTP log] Connected FTP server (#{@ip}:#{@port})"
- ftp.login(@username, @passwd)
+ @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ ftp.login(username, passwd)
ftp.binary = true
ftp.passive = true
ftp.chdir(dirname)
return bpath
end
- def cleandir(path)
+ def cleandir(path, ip, port, username, passwd)
dirname = File.dirname(path)
begin
ftp = Net::FTP.new
- if @port.nil? or @port == "" then
- ftp.connect(@ip)
+ if port.nil? or port == "" then
+ ftp.connect(ip)
else
- ftp.connect(@ip, @port)
+ ftp.connect(ip, port)
end
- @log.info "[FTP log] Connected FTP server (#{@ip}:#{@port})"
- ftp.login(@username, @passwd)
+ @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ ftp.login(username, passwd)
old_dir = ftp.pwd
ftp.chdir(dirname)
list = ftp.ls