TCL TLS

  • Creator
    Topic
  • #55335
    Dave Scoggins
    Participant

      I found myself in need of trying to create a TCL script using the TLS package. I will be using this TCL script for submission of immunization records to our state registry. I don’t see that we have TLS package installed though I do see that I can download it from the sourceforege.net website.

      When I download the .gz file and extract the files, where in my TCL directory do I want to place the files? Do they need to go in the tcllib1.14 directory or in their own directory? The file structure on the Cloverleaf server is as follows: cis6.0/integrator/tcl/lib/tcllib1.14

      Also, does anybody have a TCL script they’d be willing to share that will create a secure connection using TLSv1.2 to a vendor? I just need to get a sense of what code I need for establishing the connection and sending the VXU messages.

      Thank you for any assistance you may be able to provide.

    Viewing 1 reply thread
    • Author
      Replies
      • #85002
        David Barr
        Participant

          Here’s some code that we use.

          Code:

          #!/usr/bin/env tcl

          proc socketcmd { listenport sock ip_addr port } {
             echo [clock format [clock seconds]]: socket connected on $listenport
             set pd $::portdata($listenport)
             keylget pd USERID userid
             keylget pd PASSWORD password
             keylget pd URL url
             keylget pd RCPT rcpt

             fconfigure $sock -blocking 0 -translation binary
             fileevent $sock readable [list iocmd $listenport $sock $ip_addr $port $userid $password $url $rcpt]
          }

          proc iocmd { listenport sock ip_addr port userid password url rcpt } {
             set data “”
             echo iocmd $listenport $sock $ip_addr $port $userid $password $url $rcpt
             while { 1 } {
                 if { [eof $sock] } {
                     echo [clock format [clock seconds]]: socket closed
                     return [close $sock]
                 }
                 append data [read $sock]
                 #echo data = “{$data}”
                 if { [regexp {^.*x0b([^x0b]*)x1cx0d$} $data -> msg] } {
                     #echo msg = $msg
                     echo [clock format [clock seconds]]: received message from Cloverleaf on $listenport
                     set replymsg [postmsg $msg $url $userid $password $rcpt]
                     set data “”
                     puts -nonewline $sock “x0b$replymsgx1cx0d”
                     flush $sock
                     return
                 } else {
                     # incomplete msg
                     after 1000
                 }
             }
             close $sock
          }

          proc postmsg { msg url userid password rcpt } {
             package require http
             package require tls
             package require hl7
             ::http::register https 443 ::tls::socket

             ::tls::init -tls1 1

             set disp CONTINUE
             set errdisp ERROR

          #     puts “Message:n[join [split $msg r] n]”
          #     puts “End of messagen”

             set qry [::http::formatQuery USERID $userid PASSWORD $password MESSAGEDATA $msg]

             set result [catch {::http::geturl $url -query $qry -timeout 50000} token]
             echo http::geturl = $result
             flush stdout

             if { $result } {
                 return [myack $msg $token]
             } else {
                 upvar #0 $token state
                 if { [::http::status $token] ne “ok” } {
                     # geturl returned success, but status is not ok.
                     # this usually happens when the web server closes the
                     # connection before responding.
                     return [myack $msg “http::status = [::http::status $token]”]
                 } elseif { [::http::ncode $token] / 100 != 2 } {
                     # unsuccessful HTTP response code
                     parray state
                     return [myack $msg “http::code = [::http::code $token]”]
                 } else {
                     set replymsg [::http::data $token]
                     echo replymsg = [split $replymsg n]
                     set replymsg “[join [lsearch -inline -all -exact -not [split $replymsg n] {}] r]r”
                     set hl7 [hl7::parse_msg $replymsg]
                     if { [hl7::get_field hl7 MSA.1] eq “AE” } {
                         if { [regexp {^Not logged in:} [hl7::get_field hl7 MSA.3]] } {
                             # retry on temporary failures
                             hl7::set_field hl7 MSA.1 “AR”
                             set replymsg [hl7::join_msg hl7]
                             echo ‘received temporary error; changed to AR’
                             echo sleeping for 30 seconds
                             after 30000
                             echo done sleeping
                         } else {
                             hl7::set_field hl7 MSA.1 “AA” ;# send AA to Cloverleaf
                             set replymsg [hl7::join_msg hl7]
                             send_mail $msg $hl7 $rcpt
                         }
                     } elseif { [hl7::get_field hl7 MSA.1] eq “AR” } {
                         if { [regexp {^Processing error prevented the completion of this request:} [hl7::get_field hl7 ERR.8]] } {
                             hl7::set_field hl7 MSA.1 “AA” ;# send AA to Cloverleaf
                             send_mail $msg $hl7 $rcpt
                             hl7::delete_seg hl7 ERR
                             set replymsg [hl7::join_msg hl7]
                         }
                     }
                     echo forwarding reply from child
                     return $replymsg
                 }
             }
          }

          proc myack { msg errmsg } {
             echo creating nak message: $errmsg
             set mh [msgcreate $msg]
             keylset args2 MODE run
             keylset args2 MSGID $mh
             keylset args2 CONTEXT sms_ib_data
             set replymsg “”
             foreach dispItem [eval “hl7Raw_ack_vmc $args2″] {
                 lassign $dispItem disp newmh
                 if { $disp eq “OVER” } {
                     set replymsg [msgget $newmh]
                 }
                 msgdestroy $newmh
             }
             #echo replymsg = $replymsg
             set hl7 [hl7::parse_msg $replymsg]
             hl7::set_field hl7 MSA.1 “AR”
             hl7::set_field hl7 MSA.3 “proxy error: $errmsg”
             echo sleeping for 30 seconds
             after 30000
             echo done sleeping
             return [hl7::join_msg hl7]
          }

          proc send_mail { hl7msg hl7ack rcpt } {
             package require mime
             package require smtp

             set hl7 [hl7::parse_msg $hl7msg]
             set body “nPatient MRN: [hl7::get_field hl7 PID.3.1]”
             append body “nPatient Name: [hl7::get_field hl7 PID.5]”
             append body “nAdministration date: [hl7::get_field hl7 RXA.4]”
             append body “nAdministered code: [hl7::get_field hl7 RXA.5]”
             append body “nError message: [hl7::get_field hl7ack ERR.8]”
             append body “nMessage ID: [hl7::get_field hl7 MSH.10]”

             append body “nn[string map { r n } $hl7msg]”

             #set body [string map { r n } $hl7]
             #append body [string map { r n } [hl7::join_msg hl7ack]]

             # rxa 4 admin date
             # rxa 5 admin code

             set textT [mime::initialize -canonical text/plain -string $body]

             # create a multipart containing both, and a timestamp
             set multiT [mime::initialize -canonical multipart/mixed
                             -parts [list $textT]]

             # call Sendmail to deliver the message
             #set rcpt “David_Barr@valleymed.org”
             set rcpt2 [join $rcpt ” “]
             set fp [open “|/usr/sbin/sendmail $rcpt2” w]
             puts $fp “To: [join $rcpt ,]”
             puts $fp “From: “VMC.QDX Integrator production mode.” ”
             puts $fp “Subject: child profile error”
             #Date: Wed, 02 Mar 2008 16:34:00 -0700
             puts $fp [::mime::buildmessage $multiT]
             close $fp
          }

          set HciConnName dummy

          foreach { what port data } [read_file $HciRoot/scripts/child-proxy.cfg] {
             socket -server “socketcmd $port” $port
             set ::portdata($port) $data
          }

          vwait forever

        • #85003
          Dave Scoggins
          Participant

            Thank you David. I’ll work with it tomorrow. Hopefully it’ll work for our needs.

        Viewing 1 reply thread
        • The forum ‘Cloverleaf’ is closed to new topics and replies.