Skip to content

Commit

Permalink
merge(ssh, sftp): Merge pull request genshen#2 from genshen/refactor-…
Browse files Browse the repository at this point in the history
…ssh-io

refactor ssh io
  • Loading branch information
genshen authored Nov 15, 2018
2 parents 499c05a + 2aadcf5 commit fc4f753
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 227 deletions.
44 changes: 0 additions & 44 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,10 @@
package main

import (
"os"
"log"
"golang.org/x/crypto/ssh"
"github.com/genshen/webConsole/src/utils"
"github.com/genshen/webConsole/src/routers"
)

func main() {
routers.Run()
//setupSSH()
}

func setupSSH() {
check := func(err error, msg string) {
if err != nil {
log.Fatalf("%s error: %v", msg, err)
}
}

sshEntity := utils.SSH{
Node: utils.Node{
Host: "ssh.hpc.gensh.me",
Port: 22,
},
}
err := sshEntity.Connect("genshen", "genshen1234")
check(err, "connect")
defer sshEntity.Client.Close()

session, err := sshEntity.Client.NewSession()
check(err, "new session")
defer session.Close()

session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin

modes := ssh.TerminalModes{
ssh.ECHO: 0,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}
err = session.RequestPty("xterm", 25, 100, modes)
check(err, "request pty")

err = session.Shell()
check(err, "start shell")

err = session.Wait()
check(err, "return")
}
22 changes: 13 additions & 9 deletions src/controllers/files/sftp_utils.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package files

import (
"sync"
"github.com/pkg/sftp"
"github.com/genshen/webConsole/src/utils"
"github.com/pkg/sftp"
"log"
"sync"
)

type SftpNode utils.Node // struct alias.

type SftpEntity struct {
sshEntity *utils.SSH // from utils/ssh_utils
sftpClient *sftp.Client // sftp session created by sshEntity.Client..
sshEntity *utils.SSHShellSession // from utils/ssh_utils
sftpClient *sftp.Client // sftp session created by sshEntity.client..
}

// close sftp session and ssh client
Expand All @@ -30,7 +30,7 @@ var (
)

func NewSftpEntity(user SftpNode, username, password string) (SftpEntity, error) {
sshEntity := utils.SSH{
sshEntity := utils.SSHShellSession{
Node: utils.Node{
Host: user.Host,
Port: user.Port,
Expand All @@ -43,11 +43,15 @@ func NewSftpEntity(user SftpNode, username, password string) (SftpEntity, error)
}

// make a new sftp client
client, err := sftp.NewClient(sshEntity.Client)
if err != nil {
if sshClient, err := sshEntity.GetClient(); err != nil {
return SftpEntity{}, err
} else {
client, err := sftp.NewClient(sshClient)
if err != nil {
return SftpEntity{}, err
}
return SftpEntity{sshEntity: &sshEntity, sftpClient: client}, nil
}
return SftpEntity{sshEntity: &sshEntity, sftpClient: client}, nil
}

// add a sftp client to subscribers list.
Expand Down Expand Up @@ -75,7 +79,7 @@ func Fork(key string) (SftpEntity, bool) {
}

// make a copy of SftpEntity matched with given key.
// return sftp.Client pointer or nil pointer.
// return sftp.client pointer or nil pointer.
func ForkSftpClient(key string) (*sftp.Client) {
mutex.Lock()
defer mutex.Unlock()
Expand Down
21 changes: 9 additions & 12 deletions src/controllers/files/upload_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"net/http"
"github.com/genshen/webConsole/src/utils"
"path"
"os"
"mime/multipart"
"github.com/pkg/sftp"
)
Expand All @@ -26,35 +25,33 @@ func (f FileUpload) ServeAfterAuthenticated(w http.ResponseWriter, r *http.Reque
//file, header, err := this.GetFile("file")
r.ParseMultipartForm(32 << 20)
file, header, err := r.FormFile("file")
relativePath := r.URL.Query().Get("path") // get path. default is ""
if err != nil {
log.Println("Error: getfile err ", err)
utils.Abort(w, "error", 503)
return
}
defer file.Close()

if err := UploadFile(sftpClient, file, header); err != nil {
if err := UploadFile(relativePath, sftpClient, file, header); err != nil {
log.Println("Error: sftp error:", err)
utils.Abort(w, "message", 503)
} else {
w.Write([]byte("success"))
w.Write([]byte("success")) // todo write file name back.
}
}
}

// upload file to server via sftp.
func UploadFile(client *sftp.Client, srcFile multipart.File, header *multipart.FileHeader) error {
/**
@desPath: relative path in remote server.
*/
func UploadFile(desPath string, client *sftp.Client, srcFile multipart.File, header *multipart.FileHeader) error {
var fullPath string
if wd, err := client.Getwd(); err == nil {
fullPath = path.Join(wd, "/tmp/")
fullPath = path.Join(wd, desPath)
if _, err := client.Stat(fullPath); err != nil {
if os.IsNotExist(err) {
if err := client.Mkdir(fullPath); err != nil {
return err
}
} else {
return err
}
return err // check path must exist
}
} else {
return err
Expand Down
23 changes: 14 additions & 9 deletions src/controllers/main_controller.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package controllers

import (
"strconv"
"net/http"
"github.com/genshen/webConsole/src/models"
"github.com/genshen/webConsole/src/utils"
"net/http"
"strconv"
)

const RunModeProd = "prod"
Expand Down Expand Up @@ -40,17 +40,22 @@ func SignIn(w http.ResponseWriter, r *http.Request) {
}

if userinfo.Host != "" && userinfo.Username != "" {
//try to login ssh account
ssh := utils.SSH{}
ssh.Node.Host = userinfo.Host
ssh.Node.Port = userinfo.Port
err := ssh.Connect(userinfo.Username, userinfo.Password)
//try to login session account
session := utils.SSHShellSession{}
session.Node.Host = userinfo.Host
session.Node.Port = userinfo.Port
err := session.Connect(userinfo.Username, userinfo.Password)
if err != nil {
errUnmarshal = models.JsonResponse{HasError: true, Message: models.SIGN_IN_FORM_TYPE_ERROR_PASSWORD}
} else {
defer ssh.Close()
defer session.Close()
// create session
if session, err := ssh.Client.NewSession(); err == nil {
client, err := session.GetClient()
if err != nil {
// bad connection.
return
}
if session, err := client.NewSession(); err == nil {
if err := session.Run("whoami"); err == nil {
if token, expireUnix, err := utils.JwtNewToken(userinfo.Connection, utils.Config.Jwt.Issuer); err == nil {
errUnmarshal = models.JsonResponse{HasError: false, Addition: token}
Expand Down
21 changes: 2 additions & 19 deletions src/controllers/message_dispatcher.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package controllers

import (
"io"
"encoding/json"
"encoding/base64"
"encoding/json"
"github.com/genshen/webConsole/src/models"
"bytes"
"github.com/gorilla/websocket"
"io"
)

func DispatchMessage(messageType int, message []byte, wc io.WriteCloser) error {
Expand All @@ -29,18 +27,3 @@ func DispatchMessage(messageType int, message []byte, wc io.WriteCloser) error {
}
return nil
}

type WebSocketWriterBuffer struct {
bytes.Buffer
}

func (b *WebSocketWriterBuffer) Flush(messageType int, ws *websocket.Conn) error {
if b.Len() != 0 {
err := ws.WriteMessage(messageType, []byte(b.Bytes()))
if err != nil {
return err
}
b.Reset()
}
return nil
}
36 changes: 36 additions & 0 deletions src/controllers/websocker_copy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package controllers

import (
"bytes"
"github.com/gorilla/websocket"
"sync"
)

// copy data from WebSocket to ssh server
// and copy data from ssh server to WebSocket

// write data to WebSocket
// the data comes from ssh server.
type WebSocketBufferWriter struct {
buffer bytes.Buffer
mu sync.Mutex
}

// implement Write interface to write bytes from ssh server into bytes.Buffer.
func (w *WebSocketBufferWriter) Write(p []byte) (int, error) {
w.mu.Lock()
defer w.mu.Unlock()
return w.buffer.Write(p)
}

// flush all data in this buff into WebSocket.
func (w *WebSocketBufferWriter) Flush(messageType int, ws *websocket.Conn) error {
if w.buffer.Len() != 0 {
err := ws.WriteMessage(messageType, []byte(w.buffer.Bytes()))
if err != nil {
return err
}
w.buffer.Reset()
}
return nil
}
Loading

0 comments on commit fc4f753

Please sign in to comment.